Merge pull request #14219 from Security-Onion-Solutions/2.4/dev

2.4.120
This commit is contained in:
Mike Reeves
2025-02-12 11:14:56 -05:00
committed by GitHub
120 changed files with 5981 additions and 531599 deletions

View File

@@ -23,6 +23,7 @@ body:
- 2.4.100
- 2.4.110
- 2.4.111
- 2.4.120
- Other (please provide detail below)
validations:
required: true

View File

@@ -18,7 +18,7 @@ jobs:
with:
path-to-signatures: 'signatures_v1.json'
path-to-document: 'https://securityonionsolutions.com/cla'
allowlist: dependabot[bot],jertel,dougburks,TOoSmOotH,weslambert,defensivedepth,m0duspwnens
allowlist: dependabot[bot],jertel,dougburks,TOoSmOotH,defensivedepth,m0duspwnens
remote-organization-name: Security-Onion-Solutions
remote-repository-name: licensing

View File

@@ -1,17 +1,17 @@
### 2.4.111-20241217 ISO image released on 2024/12/18
### 2.4.120-20250212 ISO image released on 2025/02/12
### Download and Verify
2.4.111-20241217 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.111-20241217.iso
2.4.120-20250212 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.120-20250212.iso
MD5: 767823D75EB76A6DC6132F799FD0E720
SHA1: 0A7B6918FE5D4BC89EE3F2E03B4F8F4D6255141D
SHA256: 394BFCED9B5EAA0788E2D04806231B3A170839394AAF8DD23B4CE0EB9D6EF727
MD5: 3FF09F50AB1C9318CF0862DE9816102D
SHA1: 197AFA5A85C5CF95D0289FCD21BED7615FB8DB5C
SHA256: A59D94B09EEB39D8C2B6D0808792EC479B13D96FA7B32C3BEEFB6709C93F6692
Signature for ISO image:
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.111-20241217.iso.sig
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.120-20250212.iso.sig
Signing key:
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS
@@ -25,22 +25,22 @@ wget https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.
Download the signature file for the ISO:
```
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.111-20241217.iso.sig
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.120-20250212.iso.sig
```
Download the ISO image:
```
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.111-20241217.iso
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.120-20250212.iso
```
Verify the downloaded ISO image using the signature file:
```
gpg --verify securityonion-2.4.111-20241217.iso.sig securityonion-2.4.111-20241217.iso
gpg --verify securityonion-2.4.120-20250212.iso.sig securityonion-2.4.120-20250212.iso
```
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
```
gpg: Signature made Tue 17 Dec 2024 04:33:10 PM EST using RSA key ID FE507013
gpg: Signature made Tue 11 Feb 2025 05:26:33 PM EST using RSA key ID FE507013
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.

1
HOTFIX
View File

@@ -1 +0,0 @@

View File

@@ -1 +1 @@
2.4.111
2.4.120

View File

@@ -16,6 +16,8 @@ base:
- sensoroni.adv_sensoroni
- telegraf.soc_telegraf
- telegraf.adv_telegraf
- versionlock.soc_versionlock
- versionlock.adv_versionlock
'* and not *_desktop':
- firewall.soc_firewall
@@ -47,6 +49,8 @@ base:
- kibana.adv_kibana
- kratos.soc_kratos
- kratos.adv_kratos
- hydra.soc_hydra
- hydra.adv_hydra
- redis.nodes
- redis.soc_redis
- redis.adv_redis
@@ -96,6 +100,7 @@ base:
- kibana.secrets
{% endif %}
- kratos.soc_kratos
- kratos.adv_kratos
- elasticsearch.soc_elasticsearch
- elasticsearch.adv_elasticsearch
- elasticfleet.soc_elasticfleet
@@ -113,8 +118,8 @@ base:
- kibana.adv_kibana
- strelka.soc_strelka
- strelka.adv_strelka
- kratos.soc_kratos
- kratos.adv_kratos
- hydra.soc_hydra
- hydra.adv_hydra
- redis.soc_redis
- redis.adv_redis
- influxdb.soc_influxdb
@@ -149,6 +154,8 @@ base:
- idstools.adv_idstools
- kratos.soc_kratos
- kratos.adv_kratos
- hydra.soc_hydra
- hydra.adv_hydra
- redis.nodes
- redis.soc_redis
- redis.adv_redis
@@ -262,6 +269,7 @@ base:
- kibana.secrets
{% endif %}
- kratos.soc_kratos
- kratos.adv_kratos
- elasticsearch.soc_elasticsearch
- elasticsearch.adv_elasticsearch
- elasticfleet.soc_elasticfleet
@@ -277,8 +285,8 @@ base:
- kibana.adv_kibana
- backup.soc_backup
- backup.adv_backup
- kratos.soc_kratos
- kratos.adv_kratos
- hydra.soc_hydra
- hydra.adv_hydra
- redis.soc_redis
- redis.adv_redis
- influxdb.soc_influxdb

View File

@@ -24,6 +24,7 @@
'influxdb',
'soc',
'kratos',
'hydra',
'elasticfleet',
'elastic-fleet-package-registry',
'firewall',
@@ -68,6 +69,7 @@
'strelka.manager',
'soc',
'kratos',
'hydra',
'influxdb',
'telegraf',
'firewall',
@@ -95,6 +97,7 @@
'strelka.manager',
'soc',
'kratos',
'hydra',
'elasticfleet',
'elastic-fleet-package-registry',
'firewall',
@@ -117,6 +120,7 @@
'strelka.manager',
'soc',
'kratos',
'hydra',
'elastic-fleet-package-registry',
'elasticfleet',
'firewall',
@@ -151,6 +155,7 @@
'influxdb',
'soc',
'kratos',
'hydra',
'elastic-fleet-package-registry',
'elasticfleet',
'firewall',

View File

@@ -4,4 +4,5 @@ backup:
- /etc/pki
- /etc/salt
- /nsm/kratos
- /nsm/hydra
destination: "/nsm/backup"

View File

@@ -182,6 +182,7 @@ sostatus_log:
file.managed:
- name: /opt/so/log/sostatus/status.log
- mode: 644
- replace: False
# Install sostatus check cron. This is used to populate Grid.
so-status_check_cron:

View File

@@ -11,6 +11,7 @@
{% else %}
{% set UPDATE_DIR='/tmp/sogh/securityonion' %}
{% endif %}
{% set SOVERSION = salt['file.read']('/etc/soversion').strip() %}
remove_common_soup:
file.absent:
@@ -107,6 +108,17 @@ copy_so-repo-sync_sbin:
- force: True
- preserve: True
{# this is added in 2.4.120 to remove salt repo files pointing to saltproject.io to accomodate the move to broadcom and new bootstrap-salt script #}
{% if salt['pkg.version_cmp'](SOVERSION, '2.4.120') == -1 %}
{% set saltrepofile = '/etc/yum.repos.d/salt.repo' %}
{% if grains.os_family == 'Debian' %}
{% set saltrepofile = '/etc/apt/sources.list.d/salt.list' %}
{% endif %}
remove_saltproject_io_repo_manager:
file.absent:
- name: {{ saltrepofile }}
{% endif %}
{% else %}
fix_23_soup_sbin:
cmd.run:

View File

@@ -29,6 +29,7 @@ container_list() {
"so-influxdb"
"so-kibana"
"so-kratos"
"so-hydra"
"so-nginx"
"so-pcaptools"
"so-soc"
@@ -53,6 +54,7 @@ container_list() {
"so-kafka"
"so-kibana"
"so-kratos"
"so-hydra"
"so-logstash"
"so-nginx"
"so-pcaptools"

View File

@@ -125,6 +125,7 @@ if [[ $EXCLUDE_STARTUP_ERRORS == 'Y' ]]; then
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|tls handshake error" # Docker registry container when new node comes onlines
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|Unable to get license information" # Logstash trying to contact ES before it's ready
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|process already finished" # Telegraf script finished just as the auto kill timeout kicked in
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|No shard available" # Typical error when making a query before ES has finished loading all indices
fi
if [[ $EXCLUDE_FALSE_POSITIVE_ERRORS == 'Y' ]]; then
@@ -150,6 +151,7 @@ if [[ $EXCLUDE_FALSE_POSITIVE_ERRORS == 'Y' ]]; then
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|app_layer.error" # false positive (suricata 7) in stats.log e.g. app_layer.error.imap.parser | Total | 0
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|is not an ip string literal" # false positive (Open Canary logging out blank IP addresses)
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|syncing rule" # false positive (rule sync log line includes rule name which can contain 'error')
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|request_unauthorized" # false positive (login failures to Hydra result in an 'error' log)
fi
if [[ $EXCLUDE_KNOWN_ERRORS == 'Y' ]]; then
@@ -210,6 +212,7 @@ if [[ $EXCLUDE_KNOWN_ERRORS == 'Y' ]]; then
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|integrity check failed" # Detections: Exclude false positive due to automated testing
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|syncErrors" # Detections: Not an actual error
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|Initialized license manager" # SOC log: before fields.status was changed to fields.licenseStatus
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|from NIC checksum offloading" # zeek reporter.log
fi
RESULT=0
@@ -248,6 +251,9 @@ exclude_log "agentstatus.log" # ignore this log since it tracks agents in error
exclude_log "detections_runtime-status_yara.log" # temporarily ignore this log until Detections is more stable
exclude_log "/nsm/kafka/data/" # ignore Kafka data directory from log check.
# Include Zeek reporter.log to detect errors after running known good pcap(s) through sensor
echo "/nsm/zeek/spool/logger/reporter.log" >> /tmp/log_check_files
for log_file in $(cat /tmp/log_check_files); do
status "Checking log file $log_file"
tail -n $RECENT_LOG_LINES $log_file > /tmp/log_check

View File

@@ -51,6 +51,14 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
'so-hydra':
final_octet: 30
port_bindings:
- 0.0.0.0:4444:4444
- 0.0.0.0:4445:4445
custom_bind_mounts: []
extra_hosts: []
extra_env: []
'so-logstash':
final_octet: 29
port_bindings:
@@ -74,6 +82,7 @@ docker:
- 443:443
- 8443:8443
- 7788:7788
- 7789:7789
custom_bind_mounts: []
extra_hosts: []
extra_env: []

View File

@@ -45,6 +45,7 @@ docker:
so-influxdb: *dockerOptions
so-kibana: *dockerOptions
so-kratos: *dockerOptions
so-hydra: *dockerOptions
so-logstash: *dockerOptions
so-nginx: *dockerOptions
so-nginx-fleet-node: *dockerOptions

View File

@@ -63,6 +63,14 @@ eastatedir:
- group: 939
- makedirs: True
custommappingsdir:
file.directory:
- name: /nsm/custom-mappings
- user: 947
- group: 939
- makedirs: True
eapackageupgrade:
file.managed:
- name: /usr/sbin/so-elastic-fleet-package-upgrade
@@ -73,14 +81,7 @@ eapackageupgrade:
- template: jinja
{% if GLOBALS.role != "so-fleet" %}
soresourcesrepoconfig:
git.config_set:
- name: safe.directory
- value: /nsm/securityonion-resources
- global: True
- user: socore
{% if not GLOBALS.airgap %}
soresourcesrepoclone:
git.latest:

View File

@@ -48,10 +48,12 @@ elasticfleet:
- cisco_ios
- cisco_ise
- cisco_meraki
- cisco_secure_email_gateway
- cisco_umbrella
- citrix_adc
- citrix_waf
- cloudflare
- cloudflare_logpush
- crowdstrike
- darktrace
- elastic_agent
@@ -107,9 +109,13 @@ elasticfleet:
- ti_anomali
- ti_cybersixgill
- ti_misp
- ti_opencti
- ti_otx
- ti_rapid7_threat_command
- ti_recordedfuture
- ti_threatq
- trendmicro
- trend_micro_vision_one
- udp
- vsphere
- windows

View File

@@ -143,7 +143,9 @@ so-elastic-fleet-integrations:
so-elastic-agent-grid-upgrade:
cmd.run:
- name: /usr/sbin/so-elastic-agent-grid-upgrade
- retry: True
- retry:
attempts: 12
interval: 5
so-elastic-fleet-integration-upgrade:
cmd.run:

View File

@@ -0,0 +1,30 @@
{
"package": {
"name": "log",
"version": ""
},
"name": "hydra-logs",
"namespace": "so",
"description": "Hydra logs",
"policy_id": "so-grid-nodes_general",
"inputs": {
"logs-logfile": {
"enabled": true,
"streams": {
"log.logs": {
"enabled": true,
"vars": {
"paths": [
"/opt/so/log/hydra/hydra.log"
],
"data_stream.dataset": "hydra",
"tags": ["so-hydra"],
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: iam\n module: hydra",
"custom": "pipeline: hydra"
}
}
}
}
},
"force": true
}

View File

@@ -0,0 +1,35 @@
{
"package": {
"name": "log",
"version": ""
},
"name": "so-ip-mappings",
"namespace": "so",
"description": "IP Description mappings",
"policy_id": "so-grid-nodes_general",
"vars": {},
"inputs": {
"logs-logfile": {
"enabled": true,
"streams": {
"log.logs": {
"enabled": true,
"vars": {
"paths": [
"/nsm/custom-mappings/ip-descriptions.csv"
],
"data_stream.dataset": "hostnamemappings",
"tags": [
"so-ip-mappings"
],
"processors": "- decode_csv_fields:\n fields:\n message: decoded.csv\n separator: \",\"\n ignore_missing: false\n overwrite_keys: true\n trim_leading_space: true\n fail_on_error: true\n\n- extract_array:\n field: decoded.csv\n mappings:\n so.ip_address: '0'\n so.description: '1'\n\n- script:\n lang: javascript\n source: >\n function process(event) {\n var ip = event.Get('so.ip_address');\n var validIpRegex = /^((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)$/\n if (!validIpRegex.test(ip)) {\n event.Cancel();\n }\n }\n- fingerprint:\n fields: [\"so.ip_address\"]\n target_field: \"@metadata._id\"\n",
"custom": ""
}
}
}
}
},
"force": true
}

View File

@@ -76,5 +76,12 @@ do
printf "\n### $GOOS/$GOARCH Installer Generated...\n"
done
printf "\n\n### Generating MSI...\n"
cp /opt/so/saltstack/local/salt/elasticfleet/files/so_agent-installers/so-elastic-agent_windows_amd64 /opt/so/saltstack/local/salt/elasticfleet/files/so_agent-installers/so-elastic-agent_windows_amd64.exe
docker run \
--mount type=bind,source=/opt/so/saltstack/local/salt/elasticfleet/files/so_agent-installers/,target=/output/ -w /output \
{{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elastic-agent-builder:{{ GLOBALS.so_version }} wixl -o so-elastic-agent_windows_amd64_msi --arch x64 /workspace/so-elastic-agent.wxs
printf "\n### MSI Generated...\n"
printf "\n### Cleaning up temp files in /nsm/elastic-agent-workspace\n"
rm -rf /nsm/elastic-agent-workspace

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,7 @@ so-elasticsearch:
{% endfor %}
{% endif %}
- environment:
{% if ELASTICSEARCH_SEED_HOSTS | length == 1 or GLOBALS.role == 'so-heavynode' %}
{% if (GLOBALS.role in GLOBALS.manager_roles and ELASTICSEARCH_SEED_HOSTS | length == 1) or GLOBALS.role == 'so-heavynode' %}
- discovery.type=single-node
{% endif %}
- ES_JAVA_OPTS=-Xms{{ GLOBALS.elasticsearch.es_heap }} -Xmx{{ GLOBALS.elasticsearch.es_heap }} -Des.transport.cname_in_publish_address=true -Dlog4j2.formatMsgNoLookups=true

View File

@@ -10,13 +10,13 @@
{ "split": { "if": "ctx.event?.dataset != null && ctx.event.dataset.contains('.')", "field": "event.dataset", "separator": "\\.", "target_field": "module_temp" } },
{ "set": { "if": "ctx.module_temp != null", "override": true, "field": "event.module", "value": "{{module_temp.0}}" } },
{ "gsub": { "if": "ctx.event?.dataset != null && ctx.event.dataset.contains('.')", "field": "event.dataset", "pattern": "^[^.]*.", "replacement": "", "target_field": "dataset_tag_temp" } },
{ "append": { "if": "ctx.dataset_tag_temp != null", "field": "tags", "value": "{{dataset_tag_temp}}" } },
{ "append": { "if": "ctx.dataset_tag_temp != null", "field": "tags", "value": "{{dataset_tag_temp}}", "allow_duplicates": false } },
{ "set": { "if": "ctx.network?.direction == 'egress'", "override": true, "field": "network.initiated", "value": "true" } },
{ "set": { "if": "ctx.network?.direction == 'ingress'", "override": true, "field": "network.initiated", "value": "false" } },
{ "set": { "if": "ctx.network?.type == 'ipv4'", "override": true, "field": "destination.ipv6", "value": "false" } },
{ "set": { "if": "ctx.network?.type == 'ipv6'", "override": true, "field": "destination.ipv6", "value": "true" } },
{ "set": { "if": "ctx.tags.0 == 'import'", "override": true, "field": "data_stream.dataset", "value": "import" } },
{ "set": { "if": "ctx.tags.0 == 'import'", "override": true, "field": "data_stream.namespace", "value": "so" } },
{ "set": { "if": "ctx.tags != null && ctx.tags.contains('import')", "override": true, "field": "data_stream.dataset", "value": "import" } },
{ "set": { "if": "ctx.tags != null && ctx.tags.contains('import')", "override": true, "field": "data_stream.namespace", "value": "so" } },
{ "date": { "if": "ctx.event?.module == 'system'", "field": "event.created", "target_field": "@timestamp","ignore_failure": true, "formats": ["yyyy-MM-dd'T'HH:mm:ss.SSSX","yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"] } },
{ "community_id":{ "if": "ctx.event?.dataset == 'endpoint.events.network'", "ignore_failure":true } },
{ "set": { "if": "ctx.event?.module == 'fim'", "override": true, "field": "event.module", "value": "file_integrity" } },

View File

@@ -0,0 +1,9 @@
{
"description" : "hydra",
"processors" : [
{"set":{"field":"audience","value":"access","override":false,"ignore_failure":true}},
{"set":{"field":"event.dataset","ignore_empty_value":true,"ignore_failure":true,"value":"hydra.{{{audience}}}","media_type":"text/plain"}},
{"set":{"field":"event.action","ignore_failure":true,"copy_from":"msg" }},
{ "pipeline": { "name": "common" } }
]
}

View File

@@ -1,7 +1,7 @@
{
"description" : "suricata.alert",
"processors" : [
{ "set": { "field": "_index", "value": "logs-suricata.alerts-so" } },
{ "set": { "if": "ctx.event?.imported != true", "field": "_index", "value": "logs-suricata.alerts-so" } },
{ "set": { "field": "tags","value": "alert" }},
{ "rename":{ "field": "message2.alert", "target_field": "rule", "ignore_failure": true } },
{ "rename":{ "field": "rule.signature", "target_field": "rule.name", "ignore_failure": true } },

View File

@@ -18,6 +18,7 @@
{ "set": { "if": "ctx.destination?.ip != null", "field": "server.ip", "value": "{{destination.ip}}" } },
{ "set": { "if": "ctx.destination?.port != null", "field": "server.port", "value": "{{destination.port}}" } },
{ "set": { "field": "observer.name", "value": "{{agent.name}}" } },
{ "append": { "if": "ctx.network?.protocol != null && ctx.network?.protocol.contains(\"openvpn\")","field": "tags","value": ["{{network.protocol}}"],"allow_duplicates": false,"ignore_failure": true}},
{ "date": { "field": "message2.ts", "target_field": "@timestamp", "formats": ["ISO8601", "UNIX"], "ignore_failure": true } },
{ "remove": { "field": ["agent"], "ignore_failure": true } },
{ "pipeline": { "name": "common" } }

View File

@@ -38,6 +38,8 @@
{ "set": { "if": "ctx.connection?.state == 'SH'", "field": "connection.state_description", "value": "Originator sent a SYN followed by a FIN, we never saw a SYN ACK from the responder (hence the connection was 'half' open)" } },
{ "set": { "if": "ctx.connection?.state == 'SHR'", "field": "connection.state_description", "value": "Responder sent a SYN ACK followed by a FIN, we never saw a SYN from the originator" } },
{ "set": { "if": "ctx.connection?.state == 'OTH'", "field": "connection.state_description", "value": "No SYN seen, just midstream traffic (a 'partial connection' that was not later closed)" } },
{ "set": { "if": "ctx.network?.protocol != null && ctx.network?.protocol.contains(\"ipsec\")", "field": "network.protocol", "value": "ipsec"}},
{ "set": { "if": "ctx.network?.protocol != null && ctx.network?.protocol.contains(\"openvpn\")", "field": "network.protocol", "value": "openvpn"}},
{ "pipeline": { "name": "zeek.common" } }
]
}

View File

@@ -0,0 +1,37 @@
{
"description" : "zeek.http2",
"processors" : [
{ "set": { "field": "event.dataset", "value": "http2" } },
{ "set": { "field": "network.transport", "value": "tcp" } },
{ "json": { "field": "message", "target_field": "message2", "ignore_failure": true } },
{ "rename": { "field": "message2.trans_depth", "target_field": "http.trans_depth", "ignore_missing": true } },
{ "rename": { "field": "message2.method", "target_field": "http.method", "ignore_missing": true } },
{ "rename": { "field": "message2.host", "target_field": "http.virtual_host", "ignore_missing": true } },
{ "rename": { "field": "message2.uri", "target_field": "http.uri", "ignore_missing": true } },
{ "rename": { "field": "message2.referrer", "target_field": "http.referrer", "ignore_missing": true } },
{ "rename": { "field": "message2.version", "target_field": "http.version", "ignore_missing": true } },
{ "rename": { "field": "message2.user_agent", "target_field": "http.useragent", "ignore_missing": true } },
{ "rename": { "field": "message2.request_body_len", "target_field": "http.request.body.length", "ignore_missing": true } },
{ "rename": { "field": "message2.response_body_len", "target_field": "http.response.body.length", "ignore_missing": true } },
{ "rename": { "field": "message2.status_code", "target_field": "http.status_code", "ignore_missing": true } },
{ "rename": { "field": "message2.status_msg", "target_field": "http.status_message", "ignore_missing": true } },
{ "rename": { "field": "message2.info_code", "target_field": "http.info_code", "ignore_missing": true } },
{ "rename": { "field": "message2.info_msg", "target_field": "http.info_message", "ignore_missing": true } },
{ "rename": { "field": "message2.username", "target_field": "http.user", "ignore_missing": true } },
{ "rename": { "field": "message2.password", "target_field": "http.password", "ignore_missing": true } },
{ "rename": { "field": "message2.proxied", "target_field": "http.proxied", "ignore_missing": true } },
{ "rename": { "field": "message2.orig_fuids", "target_field": "log.id.orig_fuids", "ignore_missing": true } },
{ "rename": { "field": "message2.orig_filenames", "target_field": "file.orig_filenames", "ignore_missing": true } },
{ "rename": { "field": "message2.orig_mime_types", "target_field": "file.orig_mime_types", "ignore_missing": true } },
{ "rename": { "field": "message2.resp_fuids", "target_field": "log.id.resp_fuids", "ignore_missing": true } },
{ "rename": { "field": "message2.resp_filenames", "target_field": "file.resp_filenames", "ignore_missing": true } },
{ "rename": { "field": "message2.resp_mime_types", "target_field": "file.resp_mime_types", "ignore_missing": true } },
{ "rename": { "field": "message2.stream_id", "target_field": "http2.stream_id", "ignore_missing": true } },
{ "remove": { "field": "message2.tags", "ignore_failure": true } },
{ "remove": { "field": ["host"], "ignore_failure": true } },
{ "script": { "lang": "painless", "source": "ctx.uri_length = ctx.uri.length()", "ignore_failure": true } },
{ "script": { "lang": "painless", "source": "ctx.useragent_length = ctx.useragent.length()", "ignore_failure": true } },
{ "script": { "lang": "painless", "source": "ctx.virtual_host_length = ctx.virtual_host.length()", "ignore_failure": true } },
{ "pipeline": { "name": "zeek.common" } }
]
}

View File

@@ -0,0 +1,38 @@
{
"description": "zeek.ipsec",
"processors": [
{"set": { "field": "event.dataset","value": "ipsec"}},
{"json": { "field": "message","target_field": "message2","ignore_failure": true}},
{"rename": {"field": "message2.initiator_spi","target_field": "ipsec.initiator_spi","ignore_missing": true}},
{"rename": {"field": "message2.responder_spi","target_field": "ipsec.responder_spi","ignore_missing": true}},
{"rename": {"field": "message2.maj_ver","target_field": "ipsec.maj_version","ignore_missing": true}},
{"rename": {"field": "message2.min_ver","target_field": "ipsec.min_version","ignore_missing": true}},
{"set": {"ignore_failure": true,"field": "ipsec.version","value": "{{ipsec.maj_version}}.{{ipsec.min_version}}"}},
{"rename": {"field": "message2.exchange_type","target_field": "ipsec.exchange_type","ignore_missing": true}},
{"rename": {"field": "message2.flag_e","target_field": "ipsec.flag_e","ignore_missing": true}},
{"rename": {"field": "message2.flag_c","target_field": "ipsec.flag_c","ignore_missing": true}},
{"rename": {"field": "message2.flag_a","target_field": "ipsec.flag_a","ignore_missing": true}},
{"rename": {"field": "message2.flag_i","target_field": "ipsec.flag_i","ignore_missing": true}},
{"rename": {"field": "message2.flag_v","target_field": "ipsec.flag_v","ignore_missing": true}},
{"rename": {"field": "message2.flag_r","target_field": "ipsec.flag_r","ignore_missing": true}},
{"rename": {"field": "message2.message_id","target_field": "ipsec.message_id","ignore_missing": true}},
{"rename": {"field": "message2.vendor_ids","target_field": "ipsec.vendor_ids","ignore_missing": true}},
{"rename": {"field": "message2.notify_messages","target_field": "ipsec.notify_messages","ignore_missing": true}},
{"rename": {"field": "message2.transforms","target_field": "ipsec.transforms","ignore_missing": true}},
{"rename": {"field": "message2.ke_dh_groups","target_field": "ipsec.ke_dh_groups","ignore_missing": true}},
{"rename": {"field": "message2.proposals","target_field": "ipsec.proposals","ignore_missing": true}},
{"rename": {"field": "message2.certificates","target_field": "ipsec.certificates","ignore_missing": true}},
{"rename": {"field": "message2.transform_attributes","target_field": "ipsec.transform_attributes","ignore_missing": true}},
{"rename": {"field": "message2.length","target_field": "ipsec.length","ignore_missing": true}},
{"rename": {"field": "message2.hash","target_field": "ipsec.hash","ignore_missing": true}},
{"rename": {"field": "message2.doi","target_field": "ipsec.doi","ignore_missing": true}},
{"rename": {"field": "message2.situation","target_field": "ipsec.situation","ignore_missing": true}},
{"script": {
"lang": "painless",
"description": "Remove ipsec fields with empty arrays",
"source": "if (ctx.containsKey('ipsec') && ctx.ipsec instanceof Map) {\n for (String field : ['certificates', 'ke_dh_groups', 'notify_messages', 'proposals', 'transforms', 'transform_attributes', 'vendor_ids']) {\n if (ctx.ipsec[field] instanceof List && ctx.ipsec[field].isEmpty()) {\n ctx.ipsec.remove(field);\n }\n }\n }",
"ignore_failure": true
}},
{"pipeline": {"name": "zeek.common"}}
]
}

View File

@@ -0,0 +1,25 @@
{
"description": "zeek.ldap",
"processors": [
{"set": {"field": "event.dataset", "value": "ldap"}},
{"json": {"field": "message", "target_field": "message2", "ignore_failure": true}},
{"rename": {"field": "message2.message_id", "target_field": "ldap.message_id", "ignore_missing": true}},
{"rename": {"field": "message2.opcode", "target_field": "ldap.opcode", "ignore_missing": true}},
{"rename": {"field": "message2.result", "target_field": "ldap.result", "ignore_missing": true}},
{"rename": {"field": "message2.diagnostic_message", "target_field": "ldap.diagnostic_message", "ignore_missing": true}},
{"rename": {"field": "message2.version", "target_field": "ldap.version", "ignore_missing": true}},
{"rename": {"field": "message2.object", "target_field": "ldap.object", "ignore_missing": true}},
{"rename": {"field": "message2.argument", "target_field": "ldap.argument", "ignore_missing": true}},
{"rename": {"field": "message2.scope", "target_field": "ldap_search.scope", "ignore_missing":true}},
{"rename": {"field": "message2.deref_aliases", "target_field": "ldap_search.deref_aliases", "ignore_missing":true}},
{"rename": {"field": "message2.base_object", "target_field": "ldap.object", "ignore_missing":true}},
{"rename": {"field": "message2.result_count", "target_field": "ldap_search.result_count", "ignore_missing":true}},
{"rename": {"field": "message2.filter", "target_field": "ldap_search.filter", "ignore_missing":true}},
{"rename": {"field": "message2.attributes", "target_field": "ldap_search.attributes", "ignore_missing":true}},
{"script": {"source": "if (ctx.containsKey('ldap') && ctx.ldap.containsKey('diagnostic_message') && ctx.ldap.diagnostic_message != null) {\n String message = ctx.ldap.diagnostic_message;\n\n // get user and property from SASL success\n if (message.toLowerCase().contains(\"sasl(0): successful result\")) {\n Pattern pattern = /user:\\s*([^ ]+)\\s*property:\\s*([^ ]+)/i;\n Matcher matcher = pattern.matcher(message);\n if (matcher.find()) {\n ctx.ldap.user_email = matcher.group(1); // Extract user email\n ctx.ldap.property = matcher.group(2); // Extract property\n }\n }\n if (message.toLowerCase().contains(\"ldaperr:\")) {\n Pattern pattern = /comment:\\s*([^,]+)/i;\n Matcher matcher = pattern.matcher(message);\n\n if (matcher.find()) {\n ctx.ldap.comment = matcher.group(1);\n }\n }\n }","ignore_failure": true}},
{"script": {"source": "if (ctx.containsKey('ldap') && ctx.ldap.containsKey('object') && ctx.ldap.object != null) {\n String message = ctx.ldap.object;\n\n // parse common name from ldap object\n if (message.toLowerCase().contains(\"cn=\")) {\n Pattern pattern = /cn=([^,]+)/i;\n Matcher matcher = pattern.matcher(message);\n if (matcher.find()) {\n ctx.ldap.common_name = matcher.group(1); // Extract CN\n }\n }\n // build domain from ldap object\n if (message.toLowerCase().contains(\"dc=\")) {\n Pattern dcPattern = /dc=([^,]+)/i;\n Matcher dcMatcher = dcPattern.matcher(message);\n\n StringBuilder domainBuilder = new StringBuilder();\n while (dcMatcher.find()) {\n if (domainBuilder.length() > 0 ){\n domainBuilder.append(\".\");\n }\n domainBuilder.append(dcMatcher.group(1));\n }\n if (domainBuilder.length() > 0) {\n ctx.ldap.domain = domainBuilder.toString();\n }\n }\n // create list of any organizational units from ldap object\n if (message.toLowerCase().contains(\"ou=\")) {\n Pattern ouPattern = /ou=([^,]+)/i;\n Matcher ouMatcher = ouPattern.matcher(message);\n ctx.ldap.organizational_unit = [];\n\n while (ouMatcher.find()) {\n ctx.ldap.organizational_unit.add(ouMatcher.group(1));\n }\n if(ctx.ldap.organizational_unit.isEmpty()) {\n ctx.remove(\"ldap.organizational_unit\");\n }\n }\n}\n","ignore_failure": true}},
{"remove": {"field": "message2.tags","ignore_failure": true}},
{"remove": {"field": ["host"],"ignore_failure": true}},
{"pipeline": {"name": "zeek.common"}}
]
}

View File

@@ -0,0 +1,9 @@
{
"description":"zeek.ldap_search",
"processors":[
{"pipeline": {"name": "zeek.ldap", "ignore_missing_pipeline":true,"ignore_failure":true}},
{"set": {"field": "event.dataset", "value":"ldap_search"}},
{"remove": {"field": "tags", "ignore_missing":true}},
{"pipeline": {"name": "zeek.common"}}
]
}

View File

@@ -0,0 +1,18 @@
{
"description" : "zeek.quic",
"processors" : [
{ "set": { "field": "event.dataset", "value": "quic" } },
{ "set": { "field": "network.transport", "value": "udp" } },
{ "json": { "field": "message", "target_field": "message2", "ignore_failure": true } },
{ "rename": { "field": "message2.version", "target_field": "quic.version", "ignore_missing": true } },
{ "rename": { "field": "message2.client_initial_dcid", "target_field": "quic.client_initial_dcid", "ignore_missing": true } },
{ "rename": { "field": "message2.client_scid", "target_field": "quic.client_scid", "ignore_missing": true } },
{ "rename": { "field": "message2.server_scid", "target_field": "quic.server_scid", "ignore_missing": true } },
{ "rename": { "field": "message2.server_name", "target_field": "quic.server_name", "ignore_missing": true } },
{ "rename": { "field": "message2.client_protocol", "target_field": "quic.client_protocol", "ignore_missing": true } },
{ "rename": { "field": "message2.history", "target_field": "quic.history", "ignore_missing": true } },
{ "remove": { "field": "message2.tags", "ignore_failure": true } },
{ "remove": { "field": ["host"], "ignore_failure": true } },
{ "pipeline": { "name": "zeek.common" } }
]
}

View File

@@ -11,7 +11,7 @@
{ "dot_expander": { "field": "version.minor2", "path": "message2", "ignore_failure": true } },
{ "rename": { "field": "message2.version.minor2", "target_field": "software.version.minor2", "ignore_missing": true } },
{ "dot_expander": { "field": "version.minor3", "path": "message2", "ignore_failure": true } },
{ "rename": { "field": "message2.version.minor3", "target_field": "version.minor3", "ignore_missing": true } },
{ "rename": { "field": "message2.version.minor3", "target_field": "software.version.minor3", "ignore_missing": true } },
{ "dot_expander": { "field": "version.addl", "path": "message2", "ignore_failure": true } },
{ "rename": { "field": "message2.version.addl", "target_field": "software.version.additional_info", "ignore_missing": true } },
{ "rename": { "field": "message2.host", "target_field": "source.ip", "ignore_missing": true } },

View File

@@ -396,8 +396,10 @@ elasticsearch:
so-logs-citrix_waf_x_log: *indexSettings
so-logs-cloudflare_x_audit: *indexSettings
so-logs-cloudflare_x_logpull: *indexSettings
so-logs-crowdstrike_x_alert: *indexSettings
so-logs-crowdstrike_x_falcon: *indexSettings
so-logs-crowdstrike_x_fdr: *indexSettings
so-logs-crowdstrike_x_host: *indexSettings
so-logs-darktrace_x_ai_analyst_alert: *indexSettings
so-logs-darktrace_x_model_breach_alert: *indexSettings
so-logs-darktrace_x_system_status_alert: *indexSettings
@@ -489,11 +491,16 @@ elasticsearch:
so-logs-ti_cybersixgill_x_threat: *indexSettings
so-logs-ti_misp_x_threat: *indexSettings
so-logs-ti_misp_x_threat_attributes: *indexSettings
so-logs-ti_opencti_x_indicator: *indexSettings
so-logs-ti_otx_x_pulses_subscribed: *indexSettings
so-logs-ti_otx_x_threat: *indexSettings
so-logs-ti_recordedfuture_x_latest_ioc-template: *indexSettings
so-logs-ti_recordedfuture_x_threat: *indexSettings
so-logs-ti_threatq_x_threat: *indexSettings
so-logs-trend_micro_vision_one_x_alert: *indexSettings
so-logs-trend_micro_vision_one_x_audit: *indexSettings
so-logs-trend_micro_vision_one_x_detection: *indexSettings
so-logs-trendmicro_x_deep_security: *indexSettings
so-logs-zscaler_zia_x_alerts: *indexSettings
so-logs-zscaler_zia_x_dns: *indexSettings
so-logs-zscaler_zia_x_firewall: *indexSettings
@@ -539,6 +546,7 @@ elasticsearch:
so-suricata_x_alerts: *indexSettings
so-import: *indexSettings
so-kratos: *indexSettings
so-hydra: *indexSettings
so-kismet: *indexSettings
so-logstash: *indexSettings
so-redis: *indexSettings

View File

@@ -603,6 +603,89 @@
}
}
},
"ipsec": {
"properties": {
"certificates": {
"ignore_above": 1024,
"type": "keyword"
},
"exchange_type": {
"type": "short"
},
"flag_a": {
"type": "boolean"
},
"flag_c": {
"type": "boolean"
},
"flag_e": {
"type": "boolean"
},
"flag_i": {
"type": "boolean"
},
"flag_r": {
"type": "boolean"
},
"flag_v": {
"type": "boolean"
},
"hash": {
"ignore_above": 1024,
"type": "keyword"
},
"initiator_spi": {
"ignore_above": 1024,
"type": "keyword"
},
"ke_dh_groups": {
"type": "short"
},
"length": {
"type": "long"
},
"maj_version": {
"type": "short"
},
"message_id": {
"type": "long"
},
"min_version": {
"type": "short"
},
"notify_messages": {
"ignore_above": 1024,
"type": "keyword"
},
"proposals": {
"type": "long"
},
"responder_spi": {
"ignore_above": 1024,
"type": "keyword"
},
"situation": {
"ignore_above": 1024,
"type": "keyword"
},
"transform_attributes": {
"ignore_above": 1024,
"type": "keyword"
},
"transforms": {
"ignore_above": 1024,
"type": "keyword"
},
"vendor_ids": {
"ignore_above": 1024,
"type": "keyword"
},
"version": {
"ignore_above": 1024,
"type": "keyword"
}
}
},
"irc": {
"properties": {
"addl": {
@@ -751,6 +834,81 @@
}
}
},
"ldap": {
"type": "object",
"properties": {
"message_id": {
"type": "short"
},
"opcode": {
"ignore_above": 1024,
"type": "keyword"
},
"result": {
"ignore_above": 1024,
"type": "keyword"
},
"diagnostic_message": {
"ignore_above": 1024,
"type": "keyword"
},
"version": {
"type": "short"
},
"object": {
"ignore_above": 1024,
"type": "keyword"
},
"argument": {
"ignore_above": 1024,
"type": "keyword"
},
"user_email": {
"ignore_above": 1024,
"type": "keyword"
},
"property": {
"ignore_above": 1024,
"type": "keyword"
},
"common_name": {
"ignore_above": 1024,
"type": "keyword"
},
"organizational_unit": {
"ignore_above": 1024,
"type": "keyword"
},
"domain": {
"ignore_above": 1024,
"type": "keyword"
}
}
},
"ldap_search": {
"type": "object",
"properties": {
"scope": {
"ignore_above": 1024,
"type": "keyword"
},
"deref_aliases": {
"ignore_above": 1024,
"type": "keyword"
},
"result_count": {
"type": "long"
},
"filter": {
"ignore_above": 1024,
"type": "keyword"
},
"attributes": {
"ignore_above": 1024,
"type": "keyword"
}
}
},
"modbus": {
"properties": {
"exception": {
@@ -1089,6 +1247,38 @@
}
}
},
"quic": {
"type": "object",
"properties": {
"server_name": {
"ignore_above": 1024,
"type": "keyword"
},
"version": {
"type": "short"
},
"client_initial_dcid": {
"ignore_above": 1024,
"type": "keyword"
},
"client_scid": {
"ignore_above": 1024,
"type": "keyword"
},
"server_scid": {
"ignore_above": 1024,
"type": "keyword"
},
"client_protocol": {
"ignore_above": 1024,
"type": "keyword"
},
"history": {
"ignore_above": 1024,
"type": "keyword"
}
}
},
"radius": {
"properties": {
"connect_info": {

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"template": {
"mappings": {
"properties": {
"host": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"related": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"destination": {
"properties":{
"ip": {
"type": "ip"
}
}
},
"source": {
"properties":{
"ip": {
"type": "ip"
}
}
}
}
}
}
}

View File

@@ -21,10 +21,10 @@
"properties": {
"publicId": {
"ignore_above": 1024,
"type": "keyword"
"type": "keyword"
},
"title": {
"ignore_above": 1024,
"ignore_above": 1024,
"type": "keyword"
},
"severity": {
@@ -38,15 +38,15 @@
"description": {
"type": "text"
},
"category": {
"category": {
"ignore_above": 1024,
"type": "keyword"
},
"product": {
"product": {
"ignore_above": 1024,
"type": "keyword"
},
"service": {
"service": {
"ignore_above": 1024,
"type": "keyword"
},
@@ -64,7 +64,7 @@
},
"tags": {
"ignore_above": 1024,
"type": "keyword"
"type": "keyword"
},
"ruleset": {
"ignore_above": 1024,
@@ -82,6 +82,12 @@
"ignore_above": 1024,
"type": "keyword"
},
"sourceCreated": {
"type": "date"
},
"sourceUpdated": {
"type": "date"
},
"overrides": {
"properties": {
"type": {
@@ -97,6 +103,9 @@
"updatedAt": {
"type": "date"
},
"note": {
"type": "text"
},
"regex": {
"type": "text"
},

View File

@@ -0,0 +1,25 @@
{
"_meta": {
"documentation": "https://www.elastic.co/guide/en/ecs/current/ecs-network.html",
"ecs_version": "1.12.2"
},
"template": {
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"so": {
"properties": {
"ip_address": {
"type": "ip"
},
"description": {
"type": "text"
}
}
}
}
}
}
}

View File

@@ -9,6 +9,7 @@
'so-influxdb',
'so-kibana',
'so-kratos',
'so-hydra',
'so-nginx',
'so-redis',
'so-soc',
@@ -30,6 +31,7 @@
'so-kafka',
'so-kibana',
'so-kratos',
'so-hydra',
'so-logstash',
'so-nginx',
'so-redis',
@@ -73,6 +75,7 @@
'so-influxdb',
'so-kibana',
'so-kratos',
'so-hydra',
'so-nginx',
'so-soc'
] %}

51
salt/hydra/config.sls Normal file
View File

@@ -0,0 +1,51 @@
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls.split('.')[0] in allowed_states %}
{% from "hydra/map.jinja" import HYDRAMERGED %}
hydradir:
file.directory:
- name: /nsm/hydra
- user: 928
- group: 928
- mode: 700
- makedirs: True
hydradbdir:
file.directory:
- name: /nsm/hydra/db
- user: 928
- group: 928
- mode: 700
- makedirs: True
hydralogdir:
file.directory:
- name: /opt/so/log/hydra
- user: 928
- group: 928
- makedirs: True
hydraconfig:
file.managed:
- name: /opt/so/conf/hydra/hydra.yaml
- source: salt://hydra/files/hydra.yaml.jinja
- user: 928
- group: 928
- mode: 600
- template: jinja
- makedirs: True
- defaults:
HYDRAMERGED: {{ HYDRAMERGED }}
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

30
salt/hydra/defaults.yaml Normal file
View File

@@ -0,0 +1,30 @@
hydra:
enabled: False
config:
serve:
public:
port: 4444
admin:
port: 4445
urls:
self:
issuer: https://URL_BASE/connect
public: https://URL_BASE/connect
admin: http://localhost:4445
secrets:
system: []
ttl:
access_token: 1h
oidc:
subject_identifiers:
supported_types:
- pairwise
- public
pairwise:
salt: ""
log:
level: debug
format: json
sqa:
opt_out: true

27
salt/hydra/disabled.sls Normal file
View File

@@ -0,0 +1,27 @@
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls.split('.')[0] in allowed_states %}
include:
- hydra.sostatus
so-hydra:
docker_container.absent:
- force: True
so-hydra_so-status.disabled:
file.comment:
- name: /opt/so/conf/so-status/so-status.conf
- regex: ^so-hydra$
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

103
salt/hydra/enabled.sls Normal file
View File

@@ -0,0 +1,103 @@
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
#
# Note: Per the Elastic License 2.0, the second limitation states:
#
# "You may not move, change, disable, or circumvent the license key functionality
# in the software, and you may not remove or obscure any functionality in the
# software that is protected by the license key."
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls.split('.')[0] in allowed_states %}
{% from 'docker/docker.map.jinja' import DOCKER %}
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% if 'api' in salt['pillar.get']('features', []) %}
include:
- hydra.config
- hydra.sostatus
so-hydra:
docker_container.running:
- image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-hydra:{{ GLOBALS.so_version }}
- hostname: hydra
- name: so-hydra
- networks:
- sobridge:
- ipv4_address: {{ DOCKER.containers['so-hydra'].ip }}
- binds:
- /opt/so/conf/hydra/:/hydra-conf:ro
- /opt/so/log/hydra/:/hydra-log:rw
- /nsm/hydra/db:/hydra-data:rw
{% if DOCKER.containers['so-hydra'].custom_bind_mounts %}
{% for BIND in DOCKER.containers['so-hydra'].custom_bind_mounts %}
- {{ BIND }}
{% endfor %}
{% endif %}
- port_bindings:
{% for BINDING in DOCKER.containers['so-hydra'].port_bindings %}
- {{ BINDING }}
{% endfor %}
{% if DOCKER.containers['so-hydra'].extra_hosts %}
- extra_hosts:
{% for XTRAHOST in DOCKER.containers['so-hydra'].extra_hosts %}
- {{ XTRAHOST }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-hydra'].extra_env %}
- environment:
{% for XTRAENV in DOCKER.containers['so-hydra'].extra_env %}
- {{ XTRAENV }}
{% endfor %}
{% endif %}
- restart_policy: unless-stopped
- watch:
- file: hydraconfig
- require:
- file: hydraconfig
- file: hydralogdir
- file: hydradir
delete_so-hydra_so-status.disabled:
file.uncomment:
- name: /opt/so/conf/so-status/so-status.conf
- regex: ^so-hydra$
wait_for_hydra:
http.wait_for_successful_query:
- name: 'http://{{ GLOBALS.manager }}:4444/'
- ssl: True
- verify_ssl: False
- status:
- 200
- 301
- 302
- 404
- status_type: list
- wait_for: 300
- request_interval: 10
- require:
- docker_container: so-hydra
{% else %}
{{sls}}_no_license_detected:
test.fail_without_changes:
- name: {{sls}}_no_license_detected
- comment:
- "This is a feature supported only for customers with a valid license.
Contact Security Onion Solutions, LLC via our website at https://securityonionsolutions.com
for more information about purchasing a license to enable this feature."
include:
- hydra.disabled
{% endif %}
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

View File

@@ -0,0 +1 @@
{{ HYDRAMERGED.config | yaml(false) }}

13
salt/hydra/init.sls Normal file
View File

@@ -0,0 +1,13 @@
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'hydra/map.jinja' import HYDRAMERGED %}
include:
{% if HYDRAMERGED.enabled %}
- hydra.enabled
{% else %}
- hydra.disabled
{% endif %}

13
salt/hydra/map.jinja Normal file
View File

@@ -0,0 +1,13 @@
{# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
https://securityonion.net/license; you may not use this file except in compliance with the
Elastic License 2.0. #}
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% import_yaml 'hydra/defaults.yaml' as HYDRADEFAULTS %}
{% do HYDRADEFAULTS.hydra.config.urls.self.update({'issuer': HYDRADEFAULTS.hydra.config.urls.self.issuer | replace("URL_BASE", GLOBALS.url_base)}) %}
{% do HYDRADEFAULTS.hydra.config.urls.self.update({'public': HYDRADEFAULTS.hydra.config.urls.self.public | replace("URL_BASE", GLOBALS.url_base)}) %}
{% do HYDRADEFAULTS.hydra.config.urls.self.update({'admin': HYDRADEFAULTS.hydra.config.urls.self.admin | replace("URL_BASE", GLOBALS.url_base)}) %}
{% set HYDRAMERGED = salt['pillar.get']('hydra', default=HYDRADEFAULTS.hydra, merge=true) %}

28
salt/hydra/soc_hydra.yaml Normal file
View File

@@ -0,0 +1,28 @@
hydra:
enabled:
description: Enables or disables the API authentication system, used for service account authentication. Enabling this feature requires a valid Security Onion license key. Defaults to False.
helpLink: connect.html
config:
ttl:
access_token:
description: Amount of time that the generated access token will be valid. Specified in the form of 2h, which means 2 hours.
global: True
forcedType: string
helpLink: connect.html
log:
level:
description: Log level to use for Kratos logs.
global: True
helpLink: connect.html
format:
description: Log output format for Kratos logs.
global: True
helpLink: connect.html
secrets:
system:
description: Secrets used for token generation. Generated during installation.
global: True
sensitive: True
advanced: True
forcedType: "[]string"
helpLink: connect.html

21
salt/hydra/sostatus.sls Normal file
View File

@@ -0,0 +1,21 @@
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls.split('.')[0] in allowed_states %}
append_so-hydra_so-status.conf:
file.append:
- name: /opt/so/conf/so-status/so-status.conf
- text: so-hydra
- unless: grep -q so-hydra /opt/so/conf/so-status/so-status.conf
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

File diff suppressed because one or more lines are too long

View File

@@ -50,6 +50,10 @@ kratos:
ui_url: https://URL_BASE/login/
registration:
ui_url: https://URL_BASE/login/
after:
oidc:
hooks:
- hook: session
default_browser_return_url: https://URL_BASE/
allowed_return_urls:
- http://127.0.0.1

View File

@@ -11,7 +11,7 @@ kratos:
helpLink: oidc.html
config:
id:
description: Customize the OIDC provider name. This name appears on the login page. Required.
description: Customize the OIDC provider name. This name appears on the login page. Required. It is strongly recommended to leave this to the default value, unless you are aware of the other configuration pieces that will be affected by changing it.
global: True
forcedType: string
helpLink: oidc.html
@@ -126,7 +126,6 @@ kratos:
issuer:
description: The name to show in the MFA authenticator app. Useful for differentiating between installations that share the same user email address.
global: True
advanced: True
helpLink: kratos.html
webauthn:
enabled:

View File

@@ -40,6 +40,16 @@ logrotate:
- extension .log
- dateext
- dateyesterday
/opt/so/log/hydra/*_x_log:
- daily
- rotate 14
- missingok
- copytruncate
- compress
- create
- extension .log
- dateext
- dateyesterday
/opt/so/log/kibana/*_x_log:
- daily
- rotate 14

View File

@@ -28,6 +28,13 @@ logrotate:
multiline: True
global: True
forcedType: "[]string"
"/opt/so/log/hydra/*_x_log":
description: List of logrotate options for this file.
title: /opt/so/log/hydra/*.log
advanced: True
multiline: True
global: True
forcedType: "[]string"
"/opt/so/log/kibana/*_x_log":
description: List of logrotate options for this file.
title: /opt/so/log/kibana/*.log

View File

@@ -1,5 +1,5 @@
{# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
https://securityonion.net/license; you may not use this file except in compliance with the
Elastic License 2.0. #}
@@ -33,13 +33,22 @@
{# Append Kafka input pipeline when Kafka is enabled #}
{% if GLOBALS.pipeline == 'KAFKA' %}
{% do LOGSTASH_MERGED.defined_pipelines.search.remove('so/0900_input_redis.conf.jinja') %}
{% do LOGSTASH_MERGED.defined_pipelines.search.append('so/0800_input_kafka.conf.jinja') %}
{% do LOGSTASH_MERGED.defined_pipelines.manager.append('so/0800_input_kafka.conf.jinja') %}
{% if 'so/0900_input_redis.conf.jinja' in LOGSTASH_MERGED.defined_pipelines.search %}
{% do LOGSTASH_MERGED.defined_pipelines.search.remove('so/0900_input_redis.conf.jinja') %}
{% endif %}
{% if 'so/0800_input_kafka.conf.jinja' not in LOGSTASH_MERGED.defined_pipelines.search %}
{% do LOGSTASH_MERGED.defined_pipelines.search.append('so/0800_input_kafka.conf.jinja') %}
{% endif %}
{% if 'so/0800_input_kafka.conf.jinja' not in LOGSTASH_MERGED.defined_pipelines.manager %}
{% do LOGSTASH_MERGED.defined_pipelines.manager.append('so/0800_input_kafka.conf.jinja') %}
{% endif %}
{% if 'so/9999_output_redis.conf.jinja' in LOGSTASH_MERGED.defined_pipelines.manager %}
{% do LOGSTASH_MERGED.defined_pipelines.manager.remove('so/9999_output_redis.conf.jinja') %}
{% endif %}
{# Disable logstash on manager & receiver nodes unless it has an override configured #}
{% if not KAFKA_LOGSTASH %}
{% if GLOBALS.role in ['so-manager', 'so-receiver'] and GLOBALS.hostname not in KAFKA_LOGSTASH %}
{% do LOGSTASH_MERGED.update({'enabled': False}) %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}

View File

@@ -1,18 +1,45 @@
output {
if "elastic-agent" in [tags] {
if [metadata][pipeline] {
if [metadata][_id] {
elasticsearch {
hosts => "{{ GLOBALS.hostname }}"
ecs_compatibility => v8
data_stream => true
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
document_id => "%{[metadata][_id]}"
pipeline => "%{[metadata][pipeline]}"
silence_errors_in_log => ["version_conflict_engine_exception"]
ssl => true
ssl_certificate_verification => false
if "elastic-agent" in [tags] and "so-ip-mappings" in [tags] {
elasticsearch {
hosts => "{{ GLOBALS.hostname }}"
data_stream => false
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
document_id => "%{[metadata][_id]}"
index => "so-ip-mappings"
silence_errors_in_log => ["version_conflict_engine_exception"]
ssl => true
ssl_certificate_verification => false
}
}
else {
if "elastic-agent" in [tags] {
if [metadata][pipeline] {
if [metadata][_id] {
elasticsearch {
hosts => "{{ GLOBALS.hostname }}"
ecs_compatibility => v8
data_stream => true
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
document_id => "%{[metadata][_id]}"
pipeline => "%{[metadata][pipeline]}"
silence_errors_in_log => ["version_conflict_engine_exception"]
ssl => true
ssl_certificate_verification => false
}
}
else {
elasticsearch {
hosts => "{{ GLOBALS.hostname }}"
ecs_compatibility => v8
data_stream => true
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
pipeline => "%{[metadata][pipeline]}"
ssl => true
ssl_certificate_verification => false
}
}
}
else {
@@ -22,22 +49,10 @@ output {
data_stream => true
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
pipeline => "%{[metadata][pipeline]}"
ssl => true
ssl_certificate_verification => false
}
}
}
else {
elasticsearch {
hosts => "{{ GLOBALS.hostname }}"
ecs_compatibility => v8
data_stream => true
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
ssl => true
ssl_certificate_verification => false
}
}
}
}

View File

@@ -6,10 +6,7 @@
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls in allowed_states %}
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% from 'strelka/map.jinja' import STRELKAMERGED %}
{% import_yaml 'manager/defaults.yaml' as MANAGERDEFAULTS %}
{% set MANAGERMERGED = salt['pillar.get']('manager', MANAGERDEFAULTS.manager, merge=true) %}
{% from 'strelka/map.jinja' import STRELKAMERGED %}
{% from 'manager/map.jinja' import MANAGERMERGED %}
include:
- salt.minion
@@ -45,6 +42,12 @@ yara_log_dir:
- user
- group
{% if GLOBALS.os_family == 'RedHat' %}
install_createrepo:
pkg.installed:
- name: createrepo_c
{% endif %}
repo_conf_dir:
file.directory:
- name: /opt/so/conf/reposync
@@ -135,6 +138,16 @@ rules_dir:
- group: socore
- makedirs: True
git_config_set_safe_dirs:
git.config_set:
- name: safe.directory
- global: True
- user: socore
- multivar:
- /nsm/rules/custom-local-repos/local-sigma
- /nsm/rules/custom-local-repos/local-yara
- /nsm/securityonion-resources
- /opt/so/conf/soc/ai_summary_repos/securityonion-resources
{% else %}
{{sls}}_state_not_allowed:

View File

@@ -4,4 +4,8 @@
Elastic License 2.0. #}
{% import_yaml 'manager/defaults.yaml' as MANAGERDEFAULTS %}
{% set MANAGERMERGED = salt['pillar.get']('manager', MANAGERDEFAULTS.manager, merge=True) %}
{% set MANAGERMERGED = salt['pillar.get']('manager', MANAGERDEFAULTS.manager, merge=True) %}
{% if grains.os != 'OEL' %}
{% do MANAGERMERGED.reposync.update({'enabled': False}) %}
{% endif %}

View File

@@ -6,6 +6,10 @@ so-user.lock:
file.missing:
- name: /var/tmp/so-user.lock
so-client.lock:
file.missing:
- name: /var/tmp/so-client.lock
# Must run before elasticsearch docker container is started!
sync_es_users:
cmd.run:

411
salt/manager/tools/sbin/so-client Executable file
View File

@@ -0,0 +1,411 @@
#!/bin/bash
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
if [[ -f /usr/sbin/so-common ]]; then
source /usr/sbin/so-common
else
source $(dirname $0)/../../../common/tools/sbin/so-common
fi
function usage() {
cat <<USAGE_EOF
Usage: $0 <operation> [supporting parameters]
where <operation> is one of the following:
list: Lists all client IDs and permissions currently defined in the oauth2 system
add: Adds a new client to the oauth2 system and outputs the generated secret
Required parameters:
--name <name>
Optional parameters:
--note <note> (defaults to blank)
--json output as JSON
delete: Deletes a client from the oauth2 system
Required parameters:
--id <id>
addperm: Grants a permission to an existing client
Required parameters:
--id <id>
--permission <permission>
delperm: Removes a permission from an existing client
Required parameters:
--id <id>
--permission <permission>
update: Updates a client name and note.
Required parameters:
--id <id>
--name <name>
--note <note>
--searchusername <run-as username>
generate-secret: Regenerates a client's secret and outputs the new secret.
Required parameters:
--id <id>
Optional parameters:
--json output as JSON
USAGE_EOF
exit 1
}
if [[ $# -lt 1 || $1 == --help || $1 == -h || $1 == -? || $1 == --h ]]; then
usage
fi
operation=$1
shift
searchUsername=__MISSING__
note=__MISSING__
while [[ $# -gt 0 ]]; do
param=$1
shift
case "$param" in
--id)
id=$(echo $1 | sed 's/"/\\"/g')
[[ ${#id} -gt 55 ]] && fail "id cannot be longer than 55 characters"
shift
;;
--permission)
perm=$(echo $1 | sed 's/"/\\"/g')
[[ ${#perm} -gt 50 ]] && fail "permission cannot be longer than 50 characters"
shift
;;
--name)
name=$(echo $1 | sed 's/"/\\"/g')
[[ ${#name} -gt 50 ]] && fail "name cannot be longer than 50 characters"
shift
;;
--note)
note=$(echo $1 | sed 's/"/\\"/g')
[[ ${#note} -gt 100 ]] && fail "note cannot be longer than 100 characters"
shift
;;
--searchusername)
searchUsername=$(echo $1 | sed 's/"/\\"/g')
[[ ${#searchUsername} -gt 50 ]] && fail "search username cannot be longer than 50 characters"
shift
;;
--json)
json=1
;;
*)
echo "Encountered unexpected parameter: $param"
usage
;;
esac
done
hydraUrl=${HYDRA_URL:-http://127.0.0.1:4445}
socRolesFile=${SOC_ROLES_FILE:-/opt/so/conf/soc/soc_clients_roles}
soUID=${SOCORE_UID:-939}
soGID=${SOCORE_GID:-939}
function lock() {
# Obtain file descriptor lock
exec 99>/var/tmp/so-client.lock || fail "Unable to create lock descriptor; if the system was not shutdown gracefully you may need to remove /var/tmp/so-client.lock manually."
flock -w 10 99 || fail "Another process is using so-client; if the system was not shutdown gracefully you may need to remove /var/tmp/so-client.lock manually."
trap 'rm -f /var/tmp/so-client.lock' EXIT
}
function fail() {
msg=$1
echo "$1"
exit 1
}
function require() {
cmd=$1
which "$1" 2>&1 > /dev/null
[[ $? != 0 ]] && fail "This script requires the following command be installed: ${cmd}"
}
# Verify this environment is capable of running this script
function verifyEnvironment() {
require "jq"
require "curl"
response=$(curl -Ss -L ${hydraUrl}/)
[[ "$response" != *"Error 404"* ]] && fail "Unable to communicate with Hydra; specify URL via HYDRA_URL environment variable"
}
function createFile() {
filename=$1
uid=$2
gid=$3
mkdir -p $(dirname "$filename")
truncate -s 0 "$filename"
chmod 600 "$filename"
chown "${uid}:${gid}" "$filename"
}
function ensureRoleFileExists() {
if [[ ! -f "$socRolesFile" ]]; then
# Generate the new roles file
rolesTmpFile="${socRolesFile}.tmp"
createFile "$rolesTmpFile" "$soUID" "$soGID"
if [[ -d "$socRolesFile" ]]; then
echo "Removing invalid roles directory created by Docker"
rm -fr "$socRolesFile"
fi
mv "${rolesTmpFile}" "${socRolesFile}"
fi
}
function listClients() {
response=$(curl -Ss -L -f ${hydraUrl}/admin/clients)
[[ $? != 0 ]] && fail "Unable to communicate with Hydra"
clientIds=$(echo "${response}" | jq -r ".[] | .client_id" | sort)
for clientId in $clientIds; do
perms=$(grep ":$clientId\$" "$socRolesFile" | cut -d: -f1 | tr '\n' ' ')
echo "$clientId: $perms"
done
}
function addClientPermission() {
id=$1
perm=$2
adjustClientPermission "$id" "$perm" "add"
}
function deleteClientPermission() {
id=$1
perm=$2
adjustClientPermission "$id" "$perm" "del"
}
function adjustClientPermission() {
identityId=$1
perm=$2
op=$3
[[ ${identityId} == "" ]] && fail "Client not found"
ensureRoleFileExists
filename="$socRolesFile"
hasPerm=0
grep "^$perm:" "$socRolesFile" | grep -q "$identityId" && hasPerm=1
if [[ "$op" == "add" ]]; then
if [[ "$hasPerm" == "1" ]]; then
echo "Client '$identityId' already has the permission: $perm"
return 1
else
echo "$perm:$identityId" >> "$filename"
fi
elif [[ "$op" == "del" ]]; then
if [[ "$hasPerm" -ne 1 ]]; then
fail "Client '$identityId' does not have the permission: $perm"
else
sed -e "\!^$perm:$identityId\$!d" "$filename" > "$filename.tmp"
cat "$filename".tmp > "$filename"
rm -f "$filename".tmp
fi
else
fail "Unsupported permission adjustment operation: $op"
fi
return 0
}
function convertNameToId() {
name=$1
name=${name//[^[:alnum:]]/_}
echo "socl_$name" | tr '[:upper:]' '[:lower:]'
}
function createClient() {
name=$1
note=$2
id=$(convertNameToId "$name")
now=$(date -u +%FT%TZ)
secret=$(get_random_value)
body=$(cat <<EOF
{
"access_token_strategy": "opaque",
"client_id": "$id",
"client_secret": "$secret",
"client_name": "$name",
"grant_types": [ "client_credentials" ],
"response_types": [ "code" ],
"metadata": {
"note": "$note",
"searchUsername": ""
}
}
EOF
)
response=$(curl -Ss -L --fail-with-body -X POST ${hydraUrl}/admin/clients -d "$body")
if [[ $? != 0 ]]; then
error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error"
fi
}
function update() {
clientId=$1
name=$2
note=$3
username=$4
body=$(cat <<EOF
[
{
"op": "replace",
"path": "/client_name",
"value": "$name"
},
{
"op": "replace",
"path": "/metadata",
"value": {
"note": "$note",
"searchUsername": "$username"
}
}
]
EOF
)
response=$(curl -Ss -L --fail-with-body -X PATCH ${hydraUrl}/admin/clients/$id -d "$body")
if [[ $? != 0 ]]; then
error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error"
fi
}
function generateSecret() {
clientId=$1
secret=$(get_random_value)
body=$(cat <<EOF
[
{
"op": "replace",
"path": "/client_secret",
"value": "$secret"
}
]
EOF
)
response=$(curl -Ss -L --fail-with-body -X PATCH ${hydraUrl}/admin/clients/$id -d "$body")
if [[ $? != 0 ]]; then
error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error"
fi
}
function deleteClient() {
identityId=$1
[[ ${identityId} == "" ]] && fail "Client not found"
response=$(curl -Ss -XDELETE -L --fail-with-body "${hydraUrl}/admin/clients/$identityId")
if [[ $? != 0 ]]; then
error=$(echo $response | jq .error)
fail "Failed to submit request to Hydra: $error"
fi
rolesTmpFile="${socRolesFile}.tmp"
createFile "$rolesTmpFile" "$soUID" "$soGID"
grep -v "$identityId" "$socRolesFile" > "$rolesTmpFile"
cat "$rolesTmpFile" > "$socRolesFile"
}
case "${operation}" in
"add")
verifyEnvironment
[[ "$name" == "" ]] && fail "A short client name must be provided"
lock
createClient "$name" "$note"
if [[ "$json" == "1" ]]; then
echo "{\"id\":\"$id\",\"secret\":\"$secret\"}"
else
echo "Successfully added client ID $id with generated secret: $secret"
fi
;;
"list")
verifyEnvironment
listClients
;;
"addperm")
verifyEnvironment
[[ "$id" == "" ]] && fail "Id must be provided"
[[ "$perm" == "" ]] && fail "Permission must be provided"
lock
if addClientPermission "$id" "$perm"; then
echo "Successfully added permission to client"
fi
;;
"delperm")
verifyEnvironment
[[ "$id" == "" ]] && fail "Id must be provided"
[[ "$perm" == "" ]] && fail "Permission must be provided"
lock
deleteClientPermission "$id" "$perm"
echo "Successfully removed permission from client"
;;
"update")
verifyEnvironment
[[ "$id" == "" ]] && fail "Id must be provided"
[[ "$name" == "" ]] && fail "Name must be provided"
[[ "$note" == "__MISSING__" ]] && fail "Note must be provided"
[[ "$searchUsername" == "__MISSING__" ]] && fail "Search Username must be provided"
lock
update "$id" "$name" "$note" "$searchUsername"
echo "Successfully updated client"
;;
"generate-secret")
verifyEnvironment
[[ "$id" == "" ]] && fail "Id must be provided"
lock
generateSecret "$id"
if [[ "$json" == "1" ]]; then
echo "{\"secret\":\"$secret\"}"
else
echo "Successfully generated secret: $secret"
fi
;;
"delete")
verifyEnvironment
[[ "$id" == "" ]] && fail "Id must be provided"
lock
deleteClient "$id"
echo "Successfully deleted client."
;;
*)
fail "Unsupported operation: $operation"
usage
;;
esac
exit 0

View File

@@ -100,23 +100,23 @@ while [[ $# -gt 0 ]]; do
shift
case "$param" in
--email)
email=$1
email=$(echo $1 | sed 's/"/\\"/g')
shift
;;
--role)
role=$1
role=$(echo $1 | sed 's/"/\\"/g')
shift
;;
--firstName)
firstName=$1
firstName=$(echo $1 | sed 's/"/\\"/g')
shift
;;
--lastName)
lastName=$1
lastName=$(echo $1 | sed 's/"/\\"/g')
shift
;;
--note)
note=$1
note=$(echo $1 | sed 's/"/\\"/g')
shift
;;
--skip-sync)
@@ -241,6 +241,10 @@ function updatePassword() {
[[ $? != 0 ]] && fail "Unable to clear aal2 identity IDs"
echo "delete from identity_credentials where identity_id='${identityId}' and identity_credential_type_id in (select id from identity_credential_types where name in ('totp', 'webauthn', 'oidc'));" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
[[ $? != 0 ]] && fail "Unable to clear aal2 identity credentials"
echo "delete from session_devices where session_id in (select id from sessions where identity_id='${identityId}');" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
[[ $? != 0 ]] && fail "Unable to clear session devices"
echo "delete from sessions where identity_id='${identityId}';" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
[[ $? != 0 ]] && fail "Unable to clear sessions"
echo "update identities set available_aal='aal1' where id='${identityId}';" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
[[ $? != 0 ]] && fail "Unable to reset aal"
fi
@@ -357,7 +361,6 @@ function syncElastic() {
random_crypt=$(get_random_value 53)
user_data_formatted=$(echo "${user_data_formatted}" | sed -r "s/^(.+:)\$/\\1\$2a\$12${random_crypt}/")
fi
echo "${user_data_formatted}" >> "$usersTmpFile"
# Append the user roles
@@ -373,7 +376,6 @@ function syncElastic() {
sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" >> "$rolesTmpFile"
[[ $? != 0 ]] && fail "Unable to read role identities from database"
done < "$socRolesFile"
else
echo "Database file or soc roles file does not exist yet, skipping users export"
fi

View File

@@ -19,6 +19,8 @@ SOUP_LOG=/root/soup.log
WHATWOULDYOUSAYYAHDOHERE=soup
whiptail_title='Security Onion UPdater'
NOTIFYCUSTOMELASTICCONFIG=false
TOPFILE=/opt/so/saltstack/default/salt/top.sls
BACKUPTOPFILE=/opt/so/saltstack/default/salt/top.sls.backup
# used to display messages to the user at the end of soup
declare -a FINAL_MESSAGE_QUEUE=()
@@ -32,10 +34,7 @@ check_err() {
if [[ $exit_code -ne 0 ]]; then
set +e
systemctl_func "start" "$cron_service_name"
systemctl_func "start" "salt-master"
systemctl_func "start" "salt-minion"
enable_highstate
failed_soup_restore_items
printf '%s' "Soup failed with error $exit_code: "
case $exit_code in
@@ -347,8 +346,6 @@ highstate() {
masterlock() {
echo "Locking Salt Master"
TOPFILE=/opt/so/saltstack/default/salt/top.sls
BACKUPTOPFILE=/opt/so/saltstack/default/salt/top.sls.backup
mv -v $TOPFILE $BACKUPTOPFILE
echo "base:" > $TOPFILE
echo " $MINIONID:" >> $TOPFILE
@@ -358,8 +355,12 @@ masterlock() {
}
masterunlock() {
echo "Unlocking Salt Master"
mv -v $BACKUPTOPFILE $TOPFILE
if [ -f $BACKUPTOPFILE ]; then
echo "Unlocking Salt Master"
mv -v $BACKUPTOPFILE $TOPFILE
else
echo "Salt Master does not need unlocked."
fi
}
phases_pillar_2_4_80() {
@@ -403,6 +404,8 @@ preupgrade_changes() {
[[ "$INSTALLEDVERSION" == 2.4.80 ]] && up_to_2.4.90
[[ "$INSTALLEDVERSION" == 2.4.90 ]] && up_to_2.4.100
[[ "$INSTALLEDVERSION" == 2.4.100 ]] && up_to_2.4.110
[[ "$INSTALLEDVERSION" == 2.4.110 ]] && up_to_2.4.111
[[ "$INSTALLEDVERSION" == 2.4.111 ]] && up_to_2.4.120
true
}
@@ -424,6 +427,8 @@ postupgrade_changes() {
[[ "$POSTVERSION" == 2.4.80 ]] && post_to_2.4.90
[[ "$POSTVERSION" == 2.4.90 ]] && post_to_2.4.100
[[ "$POSTVERSION" == 2.4.100 ]] && post_to_2.4.110
[[ "$POSTVERSION" == 2.4.110 ]] && post_to_2.4.111
[[ "$POSTVERSION" == 2.4.111 ]] && post_to_2.4.120
true
}
@@ -506,8 +511,7 @@ post_to_2.4.90() {
}
post_to_2.4.100() {
echo "Regenerating Elastic Agent Installers"
/sbin/so-elastic-agent-gen-installers
echo "Nothing to apply"
POSTVERSION=2.4.100
}
@@ -516,6 +520,23 @@ post_to_2.4.110() {
POSTVERSION=2.4.110
}
post_to_2.4.111() {
echo "Nothing to apply"
POSTVERSION=2.4.111
}
post_to_2.4.120() {
update_elasticsearch_index_settings
# Manually rollover suricata alerts index to ensure data_stream.dataset expected mapping is set to 'suricata'
rollover_index "logs-suricata.alerts-so"
echo "Regenerating Elastic Agent Installers"
/sbin/so-elastic-agent-gen-installers
POSTVERSION=2.4.120
}
repo_sync() {
echo "Sync the local repo."
su socore -c '/usr/sbin/so-repo-sync' || fail "Unable to complete so-repo-sync."
@@ -693,17 +714,58 @@ up_to_2.4.90() {
INSTALLEDVERSION=2.4.90
}
up_to_2.4.100() {
# Elastic Update for this release, so download Elastic Agent files
determine_elastic_agent_upgrade
INSTALLEDVERSION=2.4.100
}
up_to_2.4.110() {
echo "Nothing to do for 2.4.110"
INSTALLEDVERSION=2.4.110
}
up_to_2.4.111() {
echo "Nothing to do for 2.4.111"
INSTALLEDVERSION=2.4.111
}
up_to_2.4.120() {
add_hydra_pillars
# this is needed for the new versionlock state
mkdir -p /opt/so/saltstack/local/pillar/versionlock
touch /opt/so/saltstack/local/pillar/versionlock/adv_versionlock.sls /opt/so/saltstack/local/pillar/versionlock/soc_versionlock.sls
# New Grid Integration added this release
rm -f /opt/so/state/eaintegrations.txt
INSTALLEDVERSION=2.4.120
}
add_hydra_pillars() {
mkdir -p /opt/so/saltstack/local/pillar/hydra
touch /opt/so/saltstack/local/pillar/hydra/soc_hydra.sls
chmod 660 /opt/so/saltstack/local/pillar/hydra/soc_hydra.sls
touch /opt/so/saltstack/local/pillar/hydra/adv_hydra.sls
HYDRAKEY=$(get_random_value)
HYDRASALT=$(get_random_value)
printf '%s\n'\
"hydra:"\
" config:"\
" secrets:"\
" system:"\
" - '$HYDRAKEY'"\
" oidc:"\
" subject_identifiers:"\
" pairwise:"\
" salt: '$HYDRASALT'"\
"" > /opt/so/saltstack/local/pillar/hydra/soc_hydra.sls
}
add_detection_test_pillars() {
if [[ -n "$SOUP_INTERNAL_TESTING" ]]; then
echo "Adding detection pillar values for automated testing"
@@ -750,6 +812,22 @@ ASSIST_EOF
fi
}
rollover_index() {
idx=$1
exists=$(so-elasticsearch-query $idx -o /dev/null -w "%{http_code}")
if [[ $exists -eq 200 ]]; then
rollover=$(so-elasticsearch-query $idx/_rollover -o /dev/null -w "%{http_code}" -XPOST)
if [[ $rollover -eq 200 ]]; then
echo "Successfully triggered rollover for $idx..."
else
echo "Could not trigger rollover for $idx..."
fi
else
echo "Could not find index $idx..."
fi
}
suricata_idstools_migration() {
#Backup the pillars for idstools
mkdir -p /nsm/backup/detections-migration/idstools
@@ -913,10 +991,34 @@ update_airgap_repo() {
echo "Syncing new updates to /nsm/repo"
rsync -av $AGREPO/* /nsm/repo/
echo "Creating repo"
dnf -y install yum-utils createrepo
dnf -y install yum-utils createrepo_c
createrepo /nsm/repo
}
update_elasticsearch_index_settings() {
# Update managed indices to reflect latest index template
for idx in "so-detection" "so-detectionhistory" "so-case" "so-casehistory"; do
ilm_name=$idx
if [ "$idx" = "so-detectionhistory" ]; then
ilm_name="so-detection"
elif [ "$idx" = "so-casehistory" ]; then
ilm_name="so-case"
fi
JSON_STRING=$( jq -n --arg ILM_NAME "$ilm_name" '{"settings": {"index.auto_expand_replicas":"0-2","index.lifecycle.name":($ILM_NAME + "-logs")}}')
echo "Checking if index \"$idx\" exists"
exists=$(curl -K /opt/so/conf/elasticsearch/curl.config -s -o /dev/null -w "%{http_code}" -k -L -H "Content-Type: application/json" "https://localhost:9200/$idx")
if [ $exists -eq 200 ]; then
echo "$idx index found..."
echo "Updating $idx index settings"
curl -K /opt/so/conf/elasticsearch/curl.config -s -k -L -H "Content-Type: application/json" "https://localhost:9200/$idx/_settings" -d "$JSON_STRING" -XPUT
echo -e "\n"
else
echo -e "Skipping $idx... index does not exist\n"
fi
done
}
update_salt_mine() {
echo "Populating the mine with mine_functions for each host."
set +e
@@ -982,12 +1084,12 @@ upgrade_salt() {
# if oracle run with -r to ignore repos set by bootstrap
if [[ $OS == 'oracle' ]]; then
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -r -F -M -x python3 stable \"$NEWSALTVERSION\"" \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -r -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
# if another rhel family variant we want to run without -r to allow the bootstrap script to manage repos
else
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -F -M -x python3 stable \"$NEWSALTVERSION\"" \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
fi
set -e
@@ -1007,7 +1109,7 @@ upgrade_salt() {
echo ""
set +e
run_check_net_err \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -F -M -x python3 stable \"$NEWSALTVERSION\"" \
"sh $UPDATE_DIR/salt/salt/scripts/bootstrap-salt.sh -X -F -M stable \"$NEWSALTVERSION\"" \
"Could not update salt, please check $SOUP_LOG for details."
set -e
echo "Applying apt hold for Salt."
@@ -1091,6 +1193,16 @@ apply_hotfix() {
fi
}
failed_soup_restore_items() {
local services=("$cron_service_name" "salt-master" "salt-minion")
for SERVICE_NAME in "${services[@]}"; do
if ! systemctl is-active --quiet "$SERVICE_NAME"; then
systemctl_func "start" "$SERVICE_NAME"
fi
done
enable_highstate
masterunlock
}
#upgrade salt to 3004.1
#2_3_10_hotfix_1() {
@@ -1130,6 +1242,8 @@ main() {
echo ""
require_manager
failed_soup_restore_items
check_pillar_items
echo "Checking to see if this is an airgap install."
@@ -1301,6 +1415,10 @@ main() {
echo "Running a highstate to complete the Security Onion upgrade on this manager. This could take several minutes."
(wait_for_salt_minion "$MINIONID" "5" '/dev/stdout' || fail "Salt minion was not running or ready.") 2>&1 | tee -a "$SOUP_LOG"
# Stop long-running scripts to allow potentially updated scripts to load on the next execution.
killall salt-relay.sh
highstate
postupgrade_changes
[[ $is_airgap -eq 0 ]] && unmount_update

View File

@@ -49,33 +49,12 @@ navigatorconfig:
- makedirs: True
- template: jinja
navigatordefaultlayer:
file.managed:
- name: /opt/so/conf/navigator/layers/nav_layer_playbook.json
- source: salt://nginx/files/nav_layer_playbook.json
navigatorlayersdir:
file.directory:
- name: /opt/so/conf/navigator/layers/
- user: 939
- group: 939
- makedirs: True
- replace: False
- template: jinja
navigatorpreattack:
file.managed:
- name: /opt/so/conf/navigator/layers/pre-attack.json
- source: salt://nginx/files/pre-attack.json
- user: 939
- group: 939
- makedirs: True
- replace: False
navigatorenterpriseattack:
file.managed:
- name: /opt/so/conf/navigator/layers/enterprise-attack.json
- source: salt://nginx/files/enterprise-attack.json
- user: 939
- group: 939
- makedirs: True
- replace: False
nginx_sbin:
file.recurse:

View File

@@ -164,7 +164,6 @@ so-nginx:
- x509: managerssl_crt
{% endif%}
- file: navigatorconfig
- file: navigatordefaultlayer
{% endif %}
delete_so-nginx_so-status.disabled:

View File

@@ -89,11 +89,18 @@ http {
server_name _;
return 307 https://{{ GLOBALS.url_base }}$request_uri;
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: blob: wss:; frame-ancestors 'self'";
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header referrer-Policy no-referrer;
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256;
ssl_ecdh_curve secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
@@ -123,11 +130,19 @@ http {
http2 on;
server_name {{ GLOBALS.url_base }};
root /surirules;
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: blob: wss:; frame-ancestors 'self'";
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header referrer-Policy no-referrer;
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
location / {
@@ -153,13 +168,14 @@ http {
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header referrer-Policy no-referrer;
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
@@ -219,6 +235,37 @@ http {
proxy_set_header X-Forwarded-Proto $scheme;
}
{% if 'api' in salt['pillar.get']('features', []) %}
location ~* (^/oauth2/token.*|^.well-known/jwks.json|^.well-known/openid-configuration) {
limit_req zone=auth_throttle burst={{ NGINXMERGED.config.throttle_login_burst }} nodelay;
limit_req_status 429;
proxy_pass http://{{ GLOBALS.manager }}:4444;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /connect/ {
if ($http_authorization !~ "Bearer .*") {
return 401;
}
rewrite /connect/(.*) /api/$1 break;
proxy_pass http://{{ GLOBALS.manager }}:9822/;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_set_header x-user-id "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_set_header X-Forwarded-Proto $scheme;
}
{%- endif %}
location /cyberchef/ {
auth_request /auth/sessions/whoami;
proxy_read_timeout 90;
@@ -329,6 +376,9 @@ http {
error_page 429 = @error429;
location @error401 {
if ($request_uri ~* (^/connect/.*|^/oauth2/.*)) {
return 401;
}
if ($request_uri ~* ^/(?!(^/api/.*))) {
add_header Set-Cookie "AUTH_REDIRECT=$request_uri;Path=/;Max-Age=14400";
}
@@ -336,6 +386,9 @@ http {
}
location @error403 {
if ($request_uri ~* (^/connect/.*|^/oauth2/.*)) {
return 403;
}
add_header Set-Cookie "ory_kratos_session=;Path=/;Max-Age=0;expires=Thu, 01 Jan 1970 00:00:00 GMT;";
return 302 /auth/self-service/login/browser;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,65 +0,0 @@
{
"name": "Playbook Coverage",
"versions": {
"attack": "14",
"navigator": "4.9.1",
"layer": "4.5"
},
"domain": "enterprise-attack",
"description": "",
"filters": {
"platforms": [
"Linux",
"macOS",
"Windows",
"Network",
"PRE",
"Containers",
"Office 365",
"SaaS",
"Google Workspace",
"IaaS",
"Azure AD"
]
},
"sorting": 0,
"layout": {
"layout": "side",
"aggregateFunction": "average",
"showID": false,
"showName": true,
"showAggregateScores": false,
"countUnscored": false,
"expandedSubtechniques": "none"
},
"hideDisabled": false,
"techniques": [
{
"techniqueID": "T1197",
"tactic": "defense-evasion",
"score": 100,
"color": "",
"comment": "",
"enabled": true,
"metadata": [],
"links": [],
"showSubtechniques": false
}
],
"gradient": {
"colors": [
"#ffffff00",
"#66b1ffff"
],
"minValue": 0,
"maxValue": 100
},
"legendItems": [],
"metadata": [],
"links": [],
"showTacticRowBackground": false,
"tacticRowBackground": "#dddddd",
"selectTechniquesAcrossTactics": true,
"selectSubtechniquesWithParent": false,
"selectVisibleTechniques": false
}

View File

@@ -1,33 +1,53 @@
{%- set URL_BASE = salt['pillar.get']('global:url_base', '') %}
{
"versions": [
"collection_index_url": "",
"versions": {
"enabled": true,
"entries": [
{
"name": "ATT&CK v14",
"version": "14",
"name": "MITRE ATT&CK",
"version": "16",
"domains": [
{
{
"name": "Enterprise",
"identifier": "enterprise-attack",
"data": ["assets/so/enterprise-attack.json"]
"data": ["assets/mitre/enterprise-attack.json"]
}
]
}
],
]
},
"custom_context_menu_items": [ {"label": "view related plays","url": " https://{{URL_BASE}}/playbook/projects/detection-playbooks/issues?utf8=%E2%9C%93&set_filter=1&sort=id%3Adesc&f%5B%5D=cf_15&op%5Bcf_15%5D=%3D&f%5B%5D=&c%5B%5D=status&c%5B%5D=cf_10&c%5B%5D=cf_13&c%5B%5D=cf_18&c%5B%5D=cf_19&c%5B%5D=cf_1&c%5B%5D=updated_on&v%5Bcf_15%5D%5B%5D=~Technique_ID~"}],
"custom_context_menu_items": [
{"label": "View related Detections","url": " https://{{URL_BASE}}/#/detections?q=*{{ "{{technique_attackID}}" }}*+|+groupby+so_detection.language+|+groupby+so_detection.ruleset+so_detection.isEnabled+|+groupby+%22so_detection.category%22&z=America/New_York&el=500&gl=50&rt=0&rtu=hours"},
{"label": "View related Alerts","url": " https://{{URL_BASE}}/#/alerts?q=*{{ "{{technique_attackID}}" }}*+|+groupby+rule.name+event.module*+event.severity_label+rule.uuid&z=America/New_York&el=500&gl=500&rt=15&rtu=days"}
],
"default_layers": {
"enabled": true,
"urls": ["assets/so/nav_layer_playbook.json"]
"urls": ["assets/so/navigator_layer_all_detections.json","assets/so/navigator_layer_sigma.json","assets/so/navigator_layer_suricata.json","assets/so/navigator_layer_alerts.json"]
},
"comment_color": "yellow",
"link_color": "blue",
"banner": "",
"customize_features": [
{"name": "multiselect", "enabled": true, "description": "Disable to remove the multiselect panel from interface."},
{"name": "export_render", "enabled": true, "description": "Disable to remove the button to render the current layer."},
{"name": "export_excel", "enabled": true, "description": "Disable to remove the button to export the current layer to MS Excel (.xlsx) format."},
{"name": "legend", "enabled": true, "description": "Disable to remove the legend panel from the interface."},
{"name": "background_color", "enabled": true, "description": "Disable to remove the background color effect on manually assigned colors."},
{"name": "non_aggregate_score_color", "enabled": true, "description": "Disable to remove the color effect on non-aggregate scores."},
{"name": "aggregate_score_color", "enabled": true, "description": "Disable to remove the color effect on aggregate scores."},
{"name": "comment_underline", "enabled": true, "description": "Disable to remove the comment underline effect on techniques."},
{"name": "metadata_underline", "enabled": true, "description": "Disable to remove the metadata underline effect on techniques."},
{"name": "link_underline", "enabled": true, "description": "Disable to remove the hyperlink underline effect on techniques."}
],
"features": [
{"name": "leave_site_dialog", "enabled": true, "description": "Disable to remove the dialog prompt when leaving site."},
{"name": "tabs", "enabled": true, "description": "Disable to remove the ability to open new tabs."},
{"name": "leave_site_dialog", "enabled": false, "description": "Disable to remove the dialog prompt when leaving site."},
{"name": "tabs", "disabled": true, "description": "Disable to remove the ability to open new tabs."},
{"name": "selecting_techniques", "enabled": true, "description": "Disable to remove the ability to select techniques."},
{"name": "header", "enabled": true, "description": "Disable to remove the header containing banner."},
{"name": "subtechniques", "enabled": true, "description": "Disable to remove all sub-technique features from the interface."},

File diff suppressed because it is too large Load Diff

View File

@@ -15,9 +15,9 @@
{% if grains.saltversion|string != SALTVERSION|string %}
{% if grains.os_family|lower == 'redhat' %}
{% set UPGRADECOMMAND = 'yum clean all ; /usr/sbin/bootstrap-salt.sh -s 120 -r -F -x python3 stable ' ~ SALTVERSION %}
{% set UPGRADECOMMAND = 'yum clean all ; /usr/sbin/bootstrap-salt.sh -s 120 -r -F stable ' ~ SALTVERSION %}
{% elif grains.os_family|lower == 'debian' %}
{% set UPGRADECOMMAND = '/usr/sbin/bootstrap-salt.sh -s 120 -F -x python3 stable ' ~ SALTVERSION %}
{% set UPGRADECOMMAND = '/usr/sbin/bootstrap-salt.sh -s 120 -F stable ' ~ SALTVERSION %}
{% endif %}
{% else %}
{% set UPGRADECOMMAND = 'echo Already running Salt Minion version ' ~ SALTVERSION %}

View File

@@ -19,6 +19,17 @@ include:
{% if INSTALLEDSALTVERSION|string != SALTVERSION|string %}
{# this is added in 2.4.120 to remove salt repo files pointing to saltproject.io to accomodate the move to broadcom and new bootstrap-salt script #}
{% if salt['pkg.version_cmp'](GLOBALS.so_version, '2.4.120') == -1 %}
{% set saltrepofile = '/etc/yum.repos.d/salt.repo' %}
{% if grains.os_family == 'Debian' %}
{% set saltrepofile = '/etc/apt/sources.list.d/salt.list' %}
{% endif %}
remove_saltproject_io_repo_minion:
file.absent:
- name: {{ saltrepofile }}
{% endif %}
unhold_salt_packages:
pkg.unheld:
- pkgs:

File diff suppressed because it is too large Load Diff

View File

@@ -176,6 +176,15 @@ socusersroles:
- require:
- sls: manager.sync_es_users
socclientsroles:
file.managed:
- name: /opt/so/conf/soc/soc_clients_roles
- user: 939
- group: 939
- mode: 600
- allow_empty: true
- create: true
socuploaddir:
file.directory:
- name: /nsm/soc/uploads
@@ -198,6 +207,49 @@ socsensoronirepos:
- mode: 775
- makedirs: True
create_custom_local_yara_repo_template:
git.present:
- name: /nsm/rules/custom-local-repos/local-yara
- bare: False
- force: True
add_readme_custom_local_yara_repo_template:
file.managed:
- name: /nsm/rules/custom-local-repos/local-yara/README
- source: salt://soc/files/soc/detections_custom_repo_template_readme.jinja
- user: 939
- group: 939
- template: jinja
- context:
repo_type: "yara"
create_custom_local_sigma_repo_template:
git.present:
- name: /nsm/rules/custom-local-repos/local-sigma
- bare: False
- force: True
add_readme_custom_local_sigma_repo_template:
file.managed:
- name: /nsm/rules/custom-local-repos/local-sigma/README
- source: salt://soc/files/soc/detections_custom_repo_template_readme.jinja
- user: 939
- group: 939
- template: jinja
- context:
repo_type: "sigma"
socore_own_custom_repos:
file.directory:
- name: /nsm/rules/custom-local-repos/
- user: socore
- group: socore
- recurse:
- user
- group
{% else %}
{{sls}}_state_not_allowed:

Some files were not shown because too many files have changed in this diff Show More