Compare commits

..

21 Commits

Author SHA1 Message Date
Mike Reeves
9ddd01748c Merge pull request #15598 from Security-Onion-Solutions/2.4/main
Merge patch into dev
2026-03-13 10:48:54 -04:00
Mike Reeves
89e470059e Merge pull request #15597 from Security-Onion-Solutions/2.4.211
2.4.211
2026-03-12 13:18:19 -04:00
Mike Reeves
79b30e43d9 2.4.211 2026-03-12 11:33:11 -04:00
Mike Reeves
5cebce32f7 2.4.211 2026-03-12 11:31:59 -04:00
Josh Patterson
810681c92e Merge pull request #15593 from Security-Onion-Solutions/ulimit
set container ulimits to default
2026-03-11 14:40:40 -04:00
Josh Patterson
51f9104d0f set container ulimits to default 2026-03-11 14:37:43 -04:00
Mike Reeves
8da5ed673b Merge pull request #15586 from Security-Onion-Solutions/TOoSmOotH-patch-4
Add support for version 2.4.211 in soup script
2026-03-11 12:16:49 -04:00
Josh Patterson
83ba40b548 Merge pull request #15588 from Security-Onion-Solutions/m0duspwnens-patch-1
clear HOTFIX file
2026-03-11 12:16:21 -04:00
Josh Patterson
7de8528b34 clear HOTFIX file 2026-03-11 12:14:48 -04:00
Mike Reeves
e6bd57e08d Fix conditional check for POSTVERSION 2.4.211 2026-03-11 12:13:05 -04:00
Mike Reeves
06664440ad Add support for version 2.4.211 in soup script 2026-03-11 12:10:28 -04:00
Josh Patterson
bd31f2898b Merge pull request #15584 from Security-Onion-Solutions/hypefix
remove 10T virtual disk limit. URL_BASE to vm hosts file
2026-03-11 11:58:46 -04:00
Josh Patterson
5bf9d92b52 add URL_BASE to vm hosts file 2026-03-11 11:55:42 -04:00
Josh Patterson
48c369ed11 remove 10T limit for virtual disk 2026-03-11 11:55:01 -04:00
Josh Patterson
7fec2d59a7 Merge pull request #15583 from Security-Onion-Solutions/m0duspwnens-patch-1
fix enable/disable suricata pcap
2026-03-11 11:52:53 -04:00
Mike Reeves
a0ad589c3a Merge pull request #15582 from Security-Onion-Solutions/TOoSmOotH-patch-3
Bump version from 2.4.210 to 2.4.211
2026-03-11 11:48:51 -04:00
Mike Reeves
0bd54e2835 Add version 2.4.211 to discussion template 2026-03-11 11:44:57 -04:00
Mike Reeves
58f5c56b72 Bump version from 2.4.210 to 2.4.211 2026-03-11 11:43:42 -04:00
Josh Patterson
6472c610d0 fix enable/disable suricata pcap
suricata pcap can now be enabled/disabled through pcap:enabled grid config / pillar
2026-03-10 11:01:11 -04:00
Mike Reeves
179c1ea7f7 Merge pull request #15570 from Security-Onion-Solutions/TOoSmOotH-patch-1
Add date to HOTFIX file
2026-03-10 10:20:16 -04:00
Mike Reeves
db964cad21 Add date to HOTFIX file 2026-03-10 10:18:25 -04:00
76 changed files with 2573 additions and 609 deletions

View File

@@ -2,11 +2,13 @@ body:
- type: markdown
attributes:
value: |
⚠️ This category is solely for conversations related to Security Onion 2.4 ⚠️
If your organization needs more immediate, enterprise grade professional support, with one-on-one virtual meetings and screensharing, contact us via our website: https://securityonion.com/support
- type: dropdown
attributes:
label: Version
description: Which version of Security Onion are you asking about?
description: Which version of Security Onion 2.4.x are you asking about?
options:
-
- 2.4.10

View File

@@ -1,177 +0,0 @@
body:
- type: markdown
attributes:
value: |
If your organization needs more immediate, enterprise grade professional support, with one-on-one virtual meetings and screensharing, contact us via our website: https://securityonion.com/support
- type: dropdown
attributes:
label: Version
description: Which version of Security Onion are you asking about?
options:
-
- 3.0.0
- Other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Installation Method
description: How did you install Security Onion?
options:
-
- Security Onion ISO image
- Cloud image (Amazon, Azure, Google)
- Network installation on Oracle 9 (unsupported)
- Other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Description
description: >
Is this discussion about installation, configuration, upgrading, or other?
options:
-
- installation
- configuration
- upgrading
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Installation Type
description: >
When you installed, did you choose Import, Eval, Standalone, Distributed, or something else?
options:
-
- Import
- Eval
- Standalone
- Distributed
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Location
description: >
Is this deployment in the cloud, on-prem with Internet access, or airgap?
options:
-
- cloud
- on-prem with Internet access
- airgap
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Hardware Specs
description: >
Does your hardware meet or exceed the minimum requirements for your installation type as shown at https://securityonion.net/docs/hardware?
options:
-
- Meets minimum requirements
- Exceeds minimum requirements
- Does not meet minimum requirements
- other (please provide detail below)
validations:
required: true
- type: input
attributes:
label: CPU
description: How many CPU cores do you have?
validations:
required: true
- type: input
attributes:
label: RAM
description: How much RAM do you have?
validations:
required: true
- type: input
attributes:
label: Storage for /
description: How much storage do you have for the / partition?
validations:
required: true
- type: input
attributes:
label: Storage for /nsm
description: How much storage do you have for the /nsm partition?
validations:
required: true
- type: dropdown
attributes:
label: Network Traffic Collection
description: >
Are you collecting network traffic from a tap or span port?
options:
-
- tap
- span port
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Network Traffic Speeds
description: >
How much network traffic are you monitoring?
options:
-
- Less than 1Gbps
- 1Gbps to 10Gbps
- more than 10Gbps
validations:
required: true
- type: dropdown
attributes:
label: Status
description: >
Does SOC Grid show all services on all nodes as running OK?
options:
-
- Yes, all services on all nodes are running OK
- No, one or more services are failed (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Salt Status
description: >
Do you get any failures when you run "sudo salt-call state.highstate"?
options:
-
- Yes, there are salt failures (please provide detail below)
- No, there are no failures
validations:
required: true
- type: dropdown
attributes:
label: Logs
description: >
Are there any additional clues in /opt/so/log/?
options:
-
- Yes, there are additional clues in /opt/so/log/ (please provide detail below)
- No, there are no additional clues
validations:
required: true
- type: textarea
attributes:
label: Detail
description: Please read our discussion guidelines at https://github.com/Security-Onion-Solutions/securityonion/discussions/1720 and then provide detailed information to help us help you.
placeholder: |-
STOP! Before typing, please read our discussion guidelines at https://github.com/Security-Onion-Solutions/securityonion/discussions/1720 in their entirety!
If your organization needs more immediate, enterprise grade professional support, with one-on-one virtual meetings and screensharing, contact us via our website: https://securityonion.com/support
validations:
required: true
- type: checkboxes
attributes:
label: Guidelines
options:
- label: I have read the discussion guidelines at https://github.com/Security-Onion-Solutions/securityonion/discussions/1720 and assert that I have followed the guidelines.
required: true

View File

@@ -1,17 +1,17 @@
### 2.4.210-20260302 ISO image released on 2026/03/02
### 2.4.211-20260312 ISO image released on 2026/03/12
### Download and Verify
2.4.210-20260302 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.210-20260302.iso
2.4.211-20260312 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.211-20260312.iso
MD5: 575F316981891EBED2EE4E1F42A1F016
SHA1: 600945E8823221CBC5F1C056084A71355308227E
SHA256: A6AA6471125F07FA6E2796430E94BEAFDEF728E833E9728FDFA7106351EBC47E
MD5: 7082210AE9FF4D2634D71EAD4DC8F7A3
SHA1: F76E08C47FD786624B2385B4235A3D61A4C3E9DC
SHA256: CE6E61788DFC492E4897EEDC139D698B2EDBEB6B631DE0043F66E94AF8A0FF4E
Signature for ISO image:
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.210-20260302.iso.sig
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.211-20260312.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.210-20260302.iso.sig
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.211-20260312.iso.sig
```
Download the ISO image:
```
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.210-20260302.iso
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.211-20260312.iso
```
Verify the downloaded ISO image using the signature file:
```
gpg --verify securityonion-2.4.210-20260302.iso.sig securityonion-2.4.210-20260302.iso
gpg --verify securityonion-2.4.211-20260312.iso.sig securityonion-2.4.211-20260312.iso
```
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
```
gpg: Signature made Mon 02 Mar 2026 11:55:24 AM EST using RSA key ID FE507013
gpg: Signature made Wed 11 Mar 2026 03:05:09 PM EDT 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

@@ -0,0 +1 @@

View File

@@ -1,58 +1,50 @@
<p align="center">
<img src="https://securityonionsolutions.com/logo/logo-so-onion-dark.svg" width="400" alt="Security Onion Logo">
</p>
## Security Onion 2.4
# Security Onion
Security Onion 2.4 is here!
Security Onion is a free and open Linux distribution for threat hunting, enterprise security monitoring, and log management. It includes a comprehensive suite of tools designed to work together to provide visibility into your network and host activity.
## Screenshots
## ✨ Features
Alerts
![Alerts](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/50_alerts.png)
Security Onion includes everything you need to monitor your network and host systems:
Dashboards
![Dashboards](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/53_dashboards.png)
* **Security Onion Console (SOC)**: A unified web interface for analyzing security events and managing your grid.
* **Elastic Stack**: Powerful search backed by Elasticsearch.
* **Intrusion Detection**: Network-based IDS with Suricata and host-based monitoring with Elastic Fleet.
* **Network Metadata**: Detailed network metadata generated by Zeek or Suricata.
* **Full Packet Capture**: Retain and analyze raw network traffic with Suricata PCAP.
Hunt
![Hunt](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/56_hunt.png)
## ⭐ Security Onion Pro
Detections
![Detections](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/57_detections.png)
For organizations and enterprises requiring advanced capabilities, **Security Onion Pro** offers additional features designed for scale and efficiency:
PCAP
![PCAP](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/62_pcap.png)
* **Onion AI**: Leverage powerful AI-driven insights to accelerate your analysis and investigations.
* **Enterprise Features**: Enhanced tools and integrations tailored for enterprise-grade security operations.
Grid
![Grid](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/75_grid.png)
For more information, visit the [Security Onion Pro](https://securityonionsolutions.com/pro) page.
Config
![Config](https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion-docs/2.4/images/87_config.png)
## ☁️ Cloud Deployment
### Release Notes
Security Onion is available and ready to deploy in the **AWS**, **Azure**, and **Google Cloud (GCP)** marketplaces.
https://securityonion.net/docs/release-notes
## 🚀 Getting Started
### Requirements
| Goal | Resource |
| :--- | :--- |
| **Download** | [Security Onion ISO](https://securityonion.net/docs/download) |
| **Requirements** | [Hardware Guide](https://securityonion.net/docs/hardware) |
| **Install** | [Installation Instructions](https://securityonion.net/docs/installation) |
| **What's New** | [Release Notes](https://securityonion.net/docs/release-notes) |
https://securityonion.net/docs/hardware
## 📖 Documentation & Support
### Download
For more detailed information, please visit our [Documentation](https://docs.securityonion.net).
https://securityonion.net/docs/download
* **FAQ**: [Frequently Asked Questions](https://securityonion.net/docs/faq)
* **Community**: [Discussions & Support](https://securityonion.net/docs/community-support)
* **Training**: [Official Training](https://securityonion.net/training)
### Installation
## 🤝 Contributing
https://securityonion.net/docs/installation
We welcome contributions! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to get involved.
### FAQ
## 🛡️ License
https://securityonion.net/docs/faq
Security Onion is licensed under the terms of the license found in the [LICENSE](LICENSE) file.
### Feedback
---
*Built with 🧅 by Security Onion Solutions.*
https://securityonion.net/docs/community-support

View File

@@ -4,7 +4,6 @@
| Version | Supported |
| ------- | ------------------ |
| 3.x | :white_check_mark: |
| 2.4.x | :white_check_mark: |
| 2.3.x | :x: |
| 16.04.x | :x: |

View File

@@ -1 +1 @@
3.0.0
2.4.211

View File

@@ -87,6 +87,8 @@ base:
- zeek.adv_zeek
- bpf.soc_bpf
- bpf.adv_bpf
- pcap.soc_pcap
- pcap.adv_pcap
- suricata.soc_suricata
- suricata.adv_suricata
- minions.{{ grains.id }}
@@ -132,6 +134,8 @@ base:
- zeek.adv_zeek
- bpf.soc_bpf
- bpf.adv_bpf
- pcap.soc_pcap
- pcap.adv_pcap
- suricata.soc_suricata
- suricata.adv_suricata
- minions.{{ grains.id }}
@@ -181,6 +185,8 @@ base:
- zeek.adv_zeek
- bpf.soc_bpf
- bpf.adv_bpf
- pcap.soc_pcap
- pcap.adv_pcap
- suricata.soc_suricata
- suricata.adv_suricata
- minions.{{ grains.id }}
@@ -203,6 +209,8 @@ base:
- zeek.adv_zeek
- bpf.soc_bpf
- bpf.adv_bpf
- pcap.soc_pcap
- pcap.adv_pcap
- suricata.soc_suricata
- suricata.adv_suricata
- strelka.soc_strelka
@@ -289,6 +297,8 @@ base:
- zeek.adv_zeek
- bpf.soc_bpf
- bpf.adv_bpf
- pcap.soc_pcap
- pcap.adv_pcap
- suricata.soc_suricata
- suricata.adv_suricata
- strelka.soc_strelka

View File

@@ -38,6 +38,7 @@
] %}
{% set sensor_states = [
'pcap',
'suricata',
'healthcheck',
'tcpreplay',

View File

@@ -1,15 +1,21 @@
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% set PCAP_BPF_STATUS = 0 %}
{% set STENO_BPF_COMPILED = "" %}
{% if GLOBALS.pcap_engine == "TRANSITION" %}
{% set PCAPBPF = ["ip and host 255.255.255.1 and port 1"] %}
{% else %}
{% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %}
{% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %}
{% import 'bpf/macros.jinja' as MACROS %}
{{ MACROS.remove_comments(BPFMERGED, 'pcap') }}
{% set PCAPBPF = BPFMERGED.pcap %}
{% endif %}
{% if PCAPBPF %}
{% set PCAP_BPF_CALC = salt['cmd.script']('salt://common/tools/sbin/so-bpf-compile', GLOBALS.sensor.interface + ' ' + PCAPBPF|join(" "),cwd='/root') %}
{% if PCAP_BPF_CALC['retcode'] == 0 %}
{% set PCAP_BPF_STATUS = 1 %}
{% set STENO_BPF_COMPILED = ",\\\"--filter=" + PCAP_BPF_CALC['stdout'] + "\\\"" %}
{% endif %}
{% endif %}

View File

@@ -3,6 +3,8 @@
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% if '2.4' in salt['cp.get_file_str']('/etc/soversion') %}
{% import_yaml '/opt/so/saltstack/local/pillar/global/soc_global.sls' as SOC_GLOBAL %}
{% if SOC_GLOBAL.global.airgap %}
{% set UPDATE_DIR='/tmp/soagupdate/SecurityOnion' %}
@@ -118,3 +120,23 @@ copy_bootstrap-salt_sbin:
- source: {{UPDATE_DIR}}/salt/salt/scripts/bootstrap-salt.sh
- 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:
- name: curl -s -f -o /usr/sbin/soup https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.3/main/salt/common/tools/sbin/soup
fix_23_soup_salt:
cmd.run:
- name: curl -s -f -o /opt/so/saltstack/defalt/salt/common/tools/sbin/soup https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.3/main/salt/common/tools/sbin/soup
{% endif %}

View File

@@ -16,7 +16,7 @@
if [ "$#" -lt 2 ]; then
cat 1>&2 <<EOF
$0 compiles a BPF expression to be passed to PCAP to apply a socket filter.
$0 compiles a BPF expression to be passed to stenotype to apply a socket filter.
Its first argument is the interface (link type is required) and all other arguments
are passed to TCPDump.

View File

@@ -333,8 +333,8 @@ get_elastic_agent_vars() {
if [ -f "$defaultsfile" ]; then
ELASTIC_AGENT_TARBALL_VERSION=$(egrep " +version: " $defaultsfile | awk -F: '{print $2}' | tr -d '[:space:]')
ELASTIC_AGENT_URL="https://repo.securityonion.net/file/so-repo/prod/3/elasticagent/elastic-agent_SO-$ELASTIC_AGENT_TARBALL_VERSION.tar.gz"
ELASTIC_AGENT_MD5_URL="https://repo.securityonion.net/file/so-repo/prod/3/elasticagent/elastic-agent_SO-$ELASTIC_AGENT_TARBALL_VERSION.md5"
ELASTIC_AGENT_URL="https://repo.securityonion.net/file/so-repo/prod/2.4/elasticagent/elastic-agent_SO-$ELASTIC_AGENT_TARBALL_VERSION.tar.gz"
ELASTIC_AGENT_MD5_URL="https://repo.securityonion.net/file/so-repo/prod/2.4/elasticagent/elastic-agent_SO-$ELASTIC_AGENT_TARBALL_VERSION.md5"
ELASTIC_AGENT_FILE="/nsm/elastic-fleet/artifacts/elastic-agent_SO-$ELASTIC_AGENT_TARBALL_VERSION.tar.gz"
ELASTIC_AGENT_MD5="/nsm/elastic-fleet/artifacts/elastic-agent_SO-$ELASTIC_AGENT_TARBALL_VERSION.md5"
ELASTIC_AGENT_EXPANSION_DIR=/nsm/elastic-fleet/artifacts/beats/elastic-agent
@@ -349,16 +349,21 @@ get_random_value() {
}
gpg_rpm_import() {
if [[ "$WHATWOULDYOUSAYYAHDOHERE" == "setup" ]]; then
local RPMKEYSLOC="../salt/repo/client/files/$OS/keys"
else
local RPMKEYSLOC="$UPDATE_DIR/salt/repo/client/files/$OS/keys"
if [[ $is_oracle ]]; then
if [[ "$WHATWOULDYOUSAYYAHDOHERE" == "setup" ]]; then
local RPMKEYSLOC="../salt/repo/client/files/$OS/keys"
else
local RPMKEYSLOC="$UPDATE_DIR/salt/repo/client/files/$OS/keys"
fi
RPMKEYS=('RPM-GPG-KEY-oracle' 'RPM-GPG-KEY-EPEL-9' 'SALT-PROJECT-GPG-PUBKEY-2023.pub' 'docker.pub' 'securityonion.pub')
for RPMKEY in "${RPMKEYS[@]}"; do
rpm --import $RPMKEYSLOC/$RPMKEY
echo "Imported $RPMKEY"
done
elif [[ $is_rpm ]]; then
echo "Importing the security onion GPG key"
rpm --import ../salt/repo/client/files/oracle/keys/securityonion.pub
fi
RPMKEYS=('RPM-GPG-KEY-oracle' 'RPM-GPG-KEY-EPEL-9' 'SALT-PROJECT-GPG-PUBKEY-2023.pub' 'docker.pub' 'securityonion.pub')
for RPMKEY in "${RPMKEYS[@]}"; do
rpm --import $RPMKEYSLOC/$RPMKEY
echo "Imported $RPMKEY"
done
}
header() {
@@ -610,19 +615,69 @@ salt_minion_count() {
}
set_os() {
if [ -f /etc/redhat-release ] && grep -q "Red Hat Enterprise Linux release 9" /etc/redhat-release && [ -f /etc/oracle-release ]; then
OS=oracle
OSVER=9
is_oracle=true
is_rpm=true
if [ -f /etc/redhat-release ]; then
if grep -q "Rocky Linux release 9" /etc/redhat-release; then
OS=rocky
OSVER=9
is_rocky=true
is_rpm=true
elif grep -q "CentOS Stream release 9" /etc/redhat-release; then
OS=centos
OSVER=9
is_centos=true
is_rpm=true
elif grep -q "AlmaLinux release 9" /etc/redhat-release; then
OS=alma
OSVER=9
is_alma=true
is_rpm=true
elif grep -q "Red Hat Enterprise Linux release 9" /etc/redhat-release; then
if [ -f /etc/oracle-release ]; then
OS=oracle
OSVER=9
is_oracle=true
is_rpm=true
else
OS=rhel
OSVER=9
is_rhel=true
is_rpm=true
fi
fi
cron_service_name="crond"
elif [ -f /etc/os-release ]; then
if grep -q "UBUNTU_CODENAME=focal" /etc/os-release; then
OSVER=focal
UBVER=20.04
OS=ubuntu
is_ubuntu=true
is_deb=true
elif grep -q "UBUNTU_CODENAME=jammy" /etc/os-release; then
OSVER=jammy
UBVER=22.04
OS=ubuntu
is_ubuntu=true
is_deb=true
elif grep -q "VERSION_CODENAME=bookworm" /etc/os-release; then
OSVER=bookworm
DEBVER=12
is_debian=true
OS=debian
is_deb=true
fi
cron_service_name="cron"
fi
cron_service_name="crond"
}
set_minionid() {
MINIONID=$(lookup_grain id)
}
set_palette() {
if [[ $is_deb ]]; then
update-alternatives --set newt-palette /etc/newt/palette.original
fi
}
set_version() {
CURRENTVERSION=0.0.0

View File

@@ -32,6 +32,7 @@ container_list() {
"so-nginx"
"so-pcaptools"
"so-soc"
"so-steno"
"so-suricata"
"so-telegraf"
"so-zeek"
@@ -57,6 +58,7 @@ container_list() {
"so-pcaptools"
"so-redis"
"so-soc"
"so-steno"
"so-strelka-backend"
"so-strelka-manager"
"so-suricata"
@@ -69,6 +71,7 @@ container_list() {
"so-logstash"
"so-nginx"
"so-redis"
"so-steno"
"so-suricata"
"so-soc"
"so-telegraf"

View File

@@ -179,6 +179,7 @@ if [[ $EXCLUDE_KNOWN_ERRORS == 'Y' ]]; then
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|salt-minion-check" # bug in early 2.4 place Jinja script in non-jinja salt dir causing cron output errors
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|monitoring.metrics" # known issue with elastic agent casting the field incorrectly if an integer value shows up before a float
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|repodownload.conf" # known issue with reposync on pre-2.4.20
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|missing versions record" # stenographer corrupt index
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|soc.field." # known ingest type collisions issue with earlier versions of SO
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|error parsing signature" # Malformed Suricata rule, from upstream provider
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|sticky buffer has no matches" # Non-critical Suricata error

View File

@@ -55,22 +55,19 @@ if [ $SKIP -ne 1 ]; then
fi
delete_pcap() {
PCAP_DATA="/nsm/suripcap/"
[ -d $PCAP_DATA ] && rm -rf $PCAP_DATA/*
PCAP_DATA="/nsm/pcap/"
[ -d $PCAP_DATA ] && so-pcap-stop && rm -rf $PCAP_DATA/* && so-pcap-start
}
delete_suricata() {
SURI_LOG="/nsm/suricata/"
[ -d $SURI_LOG ] && rm -rf $SURI_LOG/*
[ -d $SURI_LOG ] && so-suricata-stop && rm -rf $SURI_LOG/* && so-suricata-start
}
delete_zeek() {
ZEEK_LOG="/nsm/zeek/logs/"
[ -d $ZEEK_LOG ] && so-zeek-stop && rm -rf $ZEEK_LOG/* && so-zeek-start
}
so-suricata-stop
delete_pcap
delete_suricata
delete_zeek
so-suricata-start

View File

@@ -23,6 +23,7 @@ if [ $# -ge 1 ]; then
fi
case $1 in
"steno") docker stop so-steno && docker rm so-steno && salt-call state.apply pcap queue=True;;
"elastic-fleet") docker stop so-elastic-fleet && docker rm so-elastic-fleet && salt-call state.apply elasticfleet queue=True;;
*) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;;
esac

View File

@@ -72,7 +72,7 @@ clean() {
done
fi
## Clean up extracted pcaps
## Clean up extracted pcaps from Steno
PCAPS='/nsm/pcapout'
OLDEST_PCAP=$(find $PCAPS -type f -printf '%T+ %p\n' | sort -n | head -n 1)
if [ -z "$OLDEST_PCAP" -o "$OLDEST_PCAP" == ".." -o "$OLDEST_PCAP" == "." ]; then

View File

@@ -23,6 +23,7 @@ if [ $# -ge 1 ]; then
case $1 in
"all") salt-call state.highstate queue=True;;
"steno") if docker ps | grep -q so-$1; then printf "\n$1 is already running!\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply pcap queue=True; fi ;;
"elastic-fleet") if docker ps | grep -q so-$1; then printf "\n$1 is already running!\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply elasticfleet queue=True; fi ;;
*) if docker ps | grep -E -q '^so-$1$'; then printf "\n$1 is already running\n\n"; else docker rm so-$1 >/dev/null 2>&1 ; salt-call state.apply $1 queue=True; fi ;;
esac

View File

@@ -174,6 +174,11 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
'so-steno':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
'so-suricata':
final_octet: 99
custom_bind_mounts: []

View File

@@ -62,6 +62,7 @@ docker:
so-idh: *dockerOptions
so-elastic-agent: *dockerOptions
so-telegraf: *dockerOptions
so-steno: *dockerOptions
so-suricata:
final_octet:
description: Last octet of the container IP address.

View File

@@ -1,3 +1,3 @@
global:
pcapengine: SURICATA
pcapengine: STENO
pipeline: REDIS

View File

@@ -18,11 +18,13 @@ global:
regexFailureMessage: You must enter either ZEEK or SURICATA.
global: True
pcapengine:
description: Which engine to use for generating pcap. Currently only SURICATA is supported.
regex: ^(SURICATA)$
description: Which engine to use for generating pcap. Options are STENO, SURICATA or TRANSITION.
regex: ^(STENO|SURICATA|TRANSITION)$
options:
- STENO
- SURICATA
regexFailureMessage: You must enter either SURICATA.
- TRANSITION
regexFailureMessage: You must enter either STENO, SURICATA or TRANSITION.
global: True
ids:
description: Which IDS engine to use. Currently only Suricata is supported.

View File

@@ -0,0 +1,27 @@
[{
"apiVersion": "influxdata.com/v2alpha1",
"kind": "CheckThreshold",
"metadata": {
"name": "steno-packet-loss"
},
"spec": {
"description": "Triggers when the average percent of packet loss is above the defined threshold. To tune this alert, modify the value for the appropriate alert level.",
"every": "1m",
"name": "Stenographer Packet Loss",
"query": "from(bucket: \"telegraf/so_short_term\")\n |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"stenodrop\")\n |\u003e filter(fn: (r) =\u003e r[\"_field\"] == \"drop\")\n |\u003e aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n |\u003e yield(name: \"mean\")",
"status": "active",
"statusMessageTemplate": "Stenographer Packet Loss on node ${r.host} has reached the ${ r._level } threshold. The current packet loss is ${ r.drop }%.",
"thresholds": [
{
"level": "CRIT",
"type": "greater",
"value": 5
},
{
"level": "WARN",
"type": "greater",
"value": 3
}
]
}
}]

File diff suppressed because one or more lines are too long

View File

@@ -180,6 +180,16 @@ logrotate:
- extension .log
- dateext
- dateyesterday
/opt/so/log/stenographer/*_x_log:
- daily
- rotate 14
- missingok
- copytruncate
- compress
- create
- extension .log
- dateext
- dateyesterday
/opt/so/log/salt/so-salt-minion-check:
- daily
- rotate 14

View File

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

View File

@@ -1,2 +1,2 @@
https://repo.securityonion.net/file/so-repo/prod/3/oracle/9
https://repo-alt.securityonion.net/prod/3/oracle/9
https://repo.securityonion.net/file/so-repo/prod/2.4/oracle/9
https://repo-alt.securityonion.net/prod/2.4/oracle/9

View File

@@ -462,14 +462,19 @@ function add_sensor_to_minion() {
echo " lb_procs: '$CORECOUNT'"
echo "suricata:"
echo " enabled: True "
echo " pcap:"
echo " enabled: True"
if [[ $is_pcaplimit ]]; then
echo " pcap:"
echo " maxsize: $MAX_PCAP_SPACE"
fi
echo " config:"
echo " af-packet:"
echo " threads: '$CORECOUNT'"
echo "pcap:"
echo " enabled: True"
if [[ $is_pcaplimit ]]; then
echo " config:"
echo " diskfreepercentage: $DFREEPERCENT"
fi
echo " "
} >> $PILLARFILE
if [ $? -ne 0 ]; then

View File

@@ -143,7 +143,7 @@ show_usage() {
echo " -v Show verbose output (files changed/added/deleted)"
echo " -vv Show very verbose output (includes file diffs)"
echo " --test Test mode - show what would change without making changes"
echo " branch Git branch to checkout (default: 3/main)"
echo " branch Git branch to checkout (default: 2.4/main)"
echo ""
echo "Examples:"
echo " $0 # Normal operation"
@@ -193,7 +193,7 @@ done
# Set default branch if not provided
if [ -z "$BRANCH" ]; then
BRANCH=3/main
BRANCH=2.4/main
fi
got_root

View File

@@ -256,7 +256,7 @@ def replacelistobject(args):
def addKey(content, key, value):
pieces = key.split(".", 1)
if len(pieces) > 1:
if pieces[0] not in content or content[pieces[0]] is None:
if not pieces[0] in content:
content[pieces[0]] = {}
addKey(content[pieces[0]], pieces[1], value)
elif key in content:
@@ -346,12 +346,7 @@ def get(args):
print(f"Key '{key}' not found by so-yaml.py", file=sys.stderr)
return 2
if isinstance(output, bool):
print(str(output).lower())
elif isinstance(output, (dict, list)):
print(yaml.safe_dump(output).strip())
else:
print(output)
print(yaml.safe_dump(output))
return 0

View File

@@ -393,7 +393,7 @@ class TestRemove(unittest.TestCase):
result = soyaml.get([filename, "key1.child2.deep1"])
self.assertEqual(result, 0)
self.assertEqual("45\n", mock_stdout.getvalue())
self.assertIn("45\n...", mock_stdout.getvalue())
def test_get_str(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
@@ -404,18 +404,7 @@ class TestRemove(unittest.TestCase):
result = soyaml.get([filename, "key1.child2.deep1"])
self.assertEqual(result, 0)
self.assertEqual("hello\n", mock_stdout.getvalue())
def test_get_bool(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
filename = "/tmp/so-yaml_test-get.yaml"
file = open(filename, "w")
file.write("{key1: { child1: 123, child2: { deep1: 45 } }, key2: false, key3: [e,f,g]}")
file.close()
result = soyaml.get([filename, "key2"])
self.assertEqual(result, 0)
self.assertEqual("false\n", mock_stdout.getvalue())
self.assertIn("hello\n...", mock_stdout.getvalue())
def test_get_list(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:

File diff suppressed because it is too large Load Diff

184
salt/manager/tools/sbin/soupto3 Executable file
View File

@@ -0,0 +1,184 @@
#!/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.
. /usr/sbin/so-common
UPDATE_URL=https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/refs/heads/3/main/VERSION
# Check if already running version 3
CURRENT_VERSION=$(cat /etc/soversion 2>/dev/null)
if [[ "$CURRENT_VERSION" =~ ^3\. ]]; then
echo ""
echo "========================================================================="
echo " Already Running Security Onion 3"
echo "========================================================================="
echo ""
echo " This system is already running Security Onion $CURRENT_VERSION."
echo " Use 'soup' to update within the 3.x release line."
echo ""
exit 0
fi
echo ""
echo "Checking PCAP settings."
echo ""
# Check pcapengine setting - must be SURICATA before upgrading to version 3
PCAP_ENGINE=$(lookup_pillar "pcapengine")
PCAP_DELETED=false
prompt_delete_pcap() {
read -rp " Would you like to delete all remaining Stenographer PCAP data? (y/N): " DELETE_PCAP
if [[ "$DELETE_PCAP" =~ ^[Yy]$ ]]; then
echo ""
echo " WARNING: This will permanently delete all Stenographer PCAP data"
echo " on all nodes. This action cannot be undone."
echo ""
read -rp " Are you sure? (y/N): " CONFIRM_DELETE
if [[ "$CONFIRM_DELETE" =~ ^[Yy]$ ]]; then
echo ""
echo " Deleting Stenographer PCAP data on all nodes..."
salt '*' cmd.run "rm -rf /nsm/pcap/* && rm -rf /nsm/pcapindex/*"
echo " Done."
PCAP_DELETED=true
else
echo ""
echo " Delete cancelled."
fi
fi
}
pcapengine_not_changed() {
echo ""
echo " PCAP engine must be set to SURICATA before upgrading to Security Onion 3."
echo " You can change this in SOC by navigating to:"
echo " Configuration -> global -> pcapengine"
}
prompt_change_engine() {
local current_engine=$1
echo ""
read -rp " Would you like to change the PCAP engine to SURICATA now? (y/N): " CHANGE_ENGINE
if [[ "$CHANGE_ENGINE" =~ ^[Yy]$ ]]; then
if [[ "$PCAP_DELETED" != "true" ]]; then
echo ""
echo " WARNING: Stenographer PCAP data was not deleted. If you proceed,"
echo " this data will no longer be accessible through SOC and will never"
echo " be automatically deleted. You will need to manually remove it later."
echo ""
read -rp " Continue with changing pcapengine to SURICATA? (y/N): " CONFIRM_CHANGE
if [[ ! "$CONFIRM_CHANGE" =~ ^[Yy]$ ]]; then
pcapengine_not_changed
return 1
fi
fi
echo ""
echo " Updating PCAP engine to SURICATA..."
so-yaml.py replace /opt/so/saltstack/local/pillar/global/soc_global.sls global.pcapengine SURICATA
echo " Done."
return 0
else
pcapengine_not_changed
return 1
fi
}
case "$PCAP_ENGINE" in
SURICATA)
echo "PCAP engine settings OK."
;;
TRANSITION|STENO)
echo ""
echo "========================================================================="
echo " PCAP Engine Check Failed"
echo "========================================================================="
echo ""
echo " Your PCAP engine is currently set to $PCAP_ENGINE."
echo ""
echo " Before upgrading to Security Onion 3, Stenographer PCAP data must be"
echo " removed and the PCAP engine must be set to SURICATA."
echo ""
echo " To check remaining Stenographer PCAP usage, run:"
echo " salt '*' cmd.run 'du -sh /nsm/pcap'"
echo ""
prompt_delete_pcap
if ! prompt_change_engine "$PCAP_ENGINE"; then
echo ""
exit 1
fi
;;
*)
echo ""
echo "========================================================================="
echo " PCAP Engine Check Failed"
echo "========================================================================="
echo ""
echo " Unable to determine the PCAP engine setting (got: '$PCAP_ENGINE')."
echo " Please ensure the PCAP engine is set to SURICATA."
echo " In SOC, navigate to Configuration -> global -> pcapengine"
echo " and change the value to SURICATA."
echo ""
exit 1
;;
esac
echo ""
echo "Checking Versions."
echo ""
# Check if Security Onion 3 has been released
VERSION=$(curl -sSf "$UPDATE_URL" 2>/dev/null)
if [[ -z "$VERSION" ]]; then
echo ""
echo "========================================================================="
echo " Unable to Check Version"
echo "========================================================================="
echo ""
echo " Could not retrieve version information from:"
echo " $UPDATE_URL"
echo ""
echo " Please check your network connection and try again."
echo ""
exit 1
fi
if [[ "$VERSION" == "UNRELEASED" ]]; then
echo ""
echo "========================================================================="
echo " Security Onion 3 Not Available"
echo "========================================================================="
echo ""
echo " Security Onion 3 has not been released yet."
echo ""
echo " Please check back later or visit https://securityonion.net for updates."
echo ""
exit 1
fi
# Validate version format (e.g., 3.0.2)
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo ""
echo "========================================================================="
echo " Invalid Version"
echo "========================================================================="
echo ""
echo " Received unexpected version format: '$VERSION'"
echo ""
echo " Please check back later or visit https://securityonion.net for updates."
echo ""
exit 1
fi
echo "Security Onion 3 ($VERSION) is available. Upgrading..."
echo ""
# All checks passed - proceed with upgrade
BRANCH=3/main soup

View File

@@ -3,7 +3,6 @@ nginx:
external_suricata: False
ssl:
replace_cert: False
alt_names: []
config:
throttle_login_burst: 12
throttle_login_rate: 20

View File

@@ -60,8 +60,6 @@ http {
{%- endif %}
{%- if GLOBALS.is_manager %}
{%- set all_names = [GLOBALS.hostname, GLOBALS.url_base] + NGINXMERGED.ssl.alt_names %}
{%- set full_server_name = all_names | unique | join(' ') %}
server {
listen 80 default_server;
@@ -71,7 +69,7 @@ http {
server {
listen 8443;
server_name {{ full_server_name }};
server_name {{ GLOBALS.url_base }};
root /opt/socore/html;
location /artifacts/ {
try_files $uri =206;
@@ -114,7 +112,7 @@ http {
server {
listen 7788;
server_name {{ full_server_name }};
server_name {{ GLOBALS.url_base }};
root /nsm/rules;
location / {
allow all;
@@ -130,7 +128,7 @@ http {
server {
listen 7789 ssl;
http2 on;
server_name {{ full_server_name }};
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'";
@@ -163,7 +161,7 @@ http {
server {
listen 443 ssl;
http2 on;
server_name {{ full_server_name }};
server_name {{ GLOBALS.url_base }};
root /opt/socore/html;
index index.html;
@@ -387,13 +385,15 @@ http {
error_page 429 = @error429;
location @error401 {
if ($request_uri ~* (^/api/.*|^/connect/.*|^/oauth2/.*)) {
if ($request_uri ~* (^/connect/.*|^/oauth2/.*)) {
return 401;
}
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
if ($request_uri ~* ^/(?!(^/api/.*))) {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}
if ($request_uri ~* ^/(?!(login|auth|oauth2|$))) {
if ($request_uri ~* ^/(?!(api/|login|auth|oauth2|$))) {
add_header Set-Cookie "AUTH_REDIRECT=$request_uri;Path=/;Max-Age=14400";
}
return 302 /auth/self-service/login/browser;

View File

@@ -30,12 +30,6 @@ nginx:
advanced: True
global: True
helpLink: nginx.html
alt_names:
description: Provide a list of alternate names to allow remote systems the ability to refer to the SOC API as another hostname.
global: True
forcedType: '[]string'
multiline: True
helpLink: nginx.html
config:
throttle_login_burst:
description: Number of login requests that can burst without triggering request throttling. Higher values allow more repeated login attempts. Values greater than zero are required in order to provide a usable login flow.

View File

@@ -49,17 +49,6 @@ managerssl_key:
- docker_container: so-nginx
# Create a cert for the reverse proxy
{% set san_list = [GLOBALS.hostname, GLOBALS.node_ip, GLOBALS.url_base] + NGINXMERGED.ssl.alt_names %}
{% set unique_san_list = san_list | unique %}
{% set managerssl_san_list = [] %}
{% for item in unique_san_list %}
{% if item | ipaddr %}
{% do managerssl_san_list.append("IP:" + item) %}
{% else %}
{% do managerssl_san_list.append("DNS:" + item) %}
{% endif %}
{% endfor %}
{% set managerssl_san = managerssl_san_list | join(', ') %}
managerssl_crt:
x509.certificate_managed:
- name: /etc/pki/managerssl.crt
@@ -67,7 +56,7 @@ managerssl_crt:
- signing_policy: managerssl
- private_key: /etc/pki/managerssl.key
- CN: {{ GLOBALS.hostname }}
- subjectAltName: {{ managerssl_san }}
- subjectAltName: "DNS:{{ GLOBALS.hostname }}, IP:{{ GLOBALS.node_ip }}, DNS:{{ GLOBALS.url_base }}"
- days_remaining: 7
- days_valid: 820
- backup: True

22
salt/pcap/ca.sls Normal file
View File

@@ -0,0 +1,22 @@
# 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 or sls in allowed_states%}
stenoca:
file.directory:
- name: /opt/so/conf/steno/certs
- user: 941
- group: 939
- makedirs: True
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

View File

@@ -1,59 +0,0 @@
# 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 %}
{% if GLOBALS.is_sensor %}
delete_so-steno_so-status.conf:
file.line:
- name: /opt/so/conf/so-status/so-status.conf
- mode: delete
- match: so-steno
remove_stenographer_user:
user.absent:
- name: stenographer
- force: True
remove_stenographer_log_dir:
file.absent:
- name: /opt/so/log/stenographer
remove_stenoloss_script:
file.absent:
- name: /opt/so/conf/telegraf/scripts/stenoloss.sh
remove_steno_conf_dir:
file.absent:
- name: /opt/so/conf/steno
remove_so_pcap_export:
file.absent:
- name: /usr/sbin/so-pcap-export
remove_so_pcap_restart:
file.absent:
- name: /usr/sbin/so-pcap-restart
remove_so_pcap_start:
file.absent:
- name: /usr/sbin/so-pcap-start
remove_so_pcap_stop:
file.absent:
- name: /usr/sbin/so-pcap-stop
so-steno:
docker_container.absent:
- force: True
{% else %}
{{sls}}.non_sensor_node:
test.show_notification:
- text: "Stenographer cleanup not applicable on non-sensor nodes."
{% endif %}

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 'pcap/defaults.yaml' as PCAPDEFAULTS %}
{% set PCAPMERGED = salt['pillar.get']('pcap', PCAPDEFAULTS.pcap, merge=True) %}
{# disable stenographer if the pcap engine is set to SURICATA #}
{% if GLOBALS.pcap_engine == "SURICATA" %}
{% do PCAPMERGED.update({'enabled': False}) %}
{% endif %}

87
salt/pcap/config.sls Normal file
View File

@@ -0,0 +1,87 @@
# 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 'vars/globals.map.jinja' import GLOBALS %}
{% from "pcap/config.map.jinja" import PCAPMERGED %}
{% from 'bpf/pcap.map.jinja' import PCAPBPF, PCAP_BPF_STATUS, PCAP_BPF_CALC, STENO_BPF_COMPILED %}
# PCAP Section
stenographergroup:
group.present:
- name: stenographer
- gid: 941
stenographer:
user.present:
- uid: 941
- gid: 941
- home: /opt/so/conf/steno
stenoconfdir:
file.directory:
- name: /opt/so/conf/steno
- user: 941
- group: 939
- makedirs: True
pcap_sbin:
file.recurse:
- name: /usr/sbin
- source: salt://pcap/tools/sbin
- user: 939
- group: 939
- file_mode: 755
{% if PCAPBPF and not PCAP_BPF_STATUS %}
stenoPCAPbpfcompilationfailure:
test.configurable_test_state:
- changes: False
- result: False
- comment: "BPF Syntax Error - Discarding Specified BPF. Error: {{ PCAP_BPF_CALC['stderr'] }}"
{% endif %}
stenoconf:
file.managed:
- name: /opt/so/conf/steno/config
- source: salt://pcap/files/config.jinja
- user: stenographer
- group: stenographer
- mode: 644
- template: jinja
- defaults:
PCAPMERGED: {{ PCAPMERGED }}
STENO_BPF_COMPILED: "{{ STENO_BPF_COMPILED }}"
pcaptmpdir:
file.directory:
- name: /nsm/pcaptmp
- user: 941
- group: 941
- makedirs: True
pcapindexdir:
file.directory:
- name: /nsm/pcapindex
- user: 941
- group: 941
- makedirs: True
stenolog:
file.directory:
- name: /opt/so/log/stenographer
- user: 941
- group: 941
- makedirs: True
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

11
salt/pcap/defaults.yaml Normal file
View File

@@ -0,0 +1,11 @@
pcap:
enabled: False
config:
maxdirectoryfiles: 30000
diskfreepercentage: 10
blocks: 2048
preallocate_file_mb: 4096
aiops: 128
pin_to_cpu: False
cpus_to_pin_to: []
disks: []

27
salt/pcap/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:
- pcap.sostatus
so-steno:
docker_container.absent:
- force: True
so-steno_so-status.disabled:
file.comment:
- name: /opt/so/conf/so-status/so-status.conf
- regex: ^so-steno$
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

63
salt/pcap/enabled.sls Normal file
View File

@@ -0,0 +1,63 @@
# 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 'vars/globals.map.jinja' import GLOBALS %}
{% from 'docker/docker.map.jinja' import DOCKER %}
include:
- pcap.ca
- pcap.config
- pcap.sostatus
so-steno:
docker_container.running:
- image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-steno:{{ GLOBALS.so_version }}
- start: True
- network_mode: host
- privileged: True
- binds:
- /opt/so/conf/steno/certs:/etc/stenographer/certs:rw
- /opt/so/conf/steno/config:/etc/stenographer/config:rw
- /nsm/pcap:/nsm/pcap:rw
- /nsm/pcapindex:/nsm/pcapindex:rw
- /nsm/pcaptmp:/tmp:rw
- /opt/so/log/stenographer:/var/log/stenographer:rw
{% if DOCKER.containers['so-steno'].custom_bind_mounts %}
{% for BIND in DOCKER.containers['so-steno'].custom_bind_mounts %}
- {{ BIND }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-steno'].extra_hosts %}
- extra_hosts:
{% for XTRAHOST in DOCKER.containers['so-steno'].extra_hosts %}
- {{ XTRAHOST }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-steno'].extra_env %}
- environment:
{% for XTRAENV in DOCKER.containers['so-steno'].extra_env %}
- {{ XTRAENV }}
{% endfor %}
{% endif %}
- watch:
- file: stenoconf
- require:
- file: stenoconf
delete_so-steno_so-status.disabled:
file.uncomment:
- name: /opt/so/conf/so-status/so-status.conf
- regex: ^so-steno$
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

View File

@@ -0,0 +1,11 @@
{
"Threads": [
{ "PacketsDirectory": "/nsm/pcap", "IndexDirectory": "/nsm/pcapindex", "MaxDirectoryFiles": {{ PCAPMERGED.config.maxdirectoryfiles }}, "DiskFreePercentage": {{ PCAPMERGED.config.diskfreepercentage }} }
]
, "StenotypePath": "/usr/bin/stenotype"
, "Interface": "{{ pillar.sensor.interface }}"
, "Port": 1234
, "Host": "127.0.0.1"
, "Flags": ["-v", "--blocks={{ PCAPMERGED.config.blocks }}", "--preallocate_file_mb={{ PCAPMERGED.config.preallocate_file_mb }}", "--aiops={{ PCAPMERGED.config.aiops }}", "--uid=stenographer", "--gid=stenographer"{{ STENO_BPF_COMPILED }}]
, "CertPath": "/etc/stenographer/certs"
}

41
salt/pcap/init.sls Normal file
View File

@@ -0,0 +1,41 @@
# 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 %}
{% from 'pcap/config.map.jinja' import PCAPMERGED %}
include:
{% if PCAPMERGED.enabled and GLOBALS.role != 'so-import'%}
- pcap.enabled
{% elif GLOBALS.role == 'so-import' %}
- pcap.config
- pcap.disabled
{% else %}
- pcap.disabled
{% endif %}
# This directory needs to exist regardless of whether STENO is enabled or not, in order for
# Sensoroni to be able to look at old steno PCAP data
# if stenographer has never run as the pcap engine no 941 user is created, so we use socore as a placeholder.
# /nsm/pcap is empty until stenographer is used as pcap engine
{% set pcap_id = 941 %}
{% set user_list = salt['user.list_users']() %}
{% if GLOBALS.pcap_engine == "SURICATA" and 'stenographer' not in user_list %}
{% set pcap_id = 939 %}
{% endif %}
pcapdir:
file.directory:
- name: /nsm/pcap
- user: {{ pcap_id }}
- group: {{ pcap_id }}
- makedirs: True
pcapoutdir:
file.directory:
- name: /nsm/pcapout
- user: 939
- group: 939
- makedirs: True

35
salt/pcap/soc_pcap.yaml Normal file
View File

@@ -0,0 +1,35 @@
pcap:
enabled:
description: Enables or disables the Stenographer packet recording process. This process may already be disabled if Suricata is being used as the packet capture process.
helpLink: stenographer.html
config:
maxdirectoryfiles:
description: By default, Stenographer limits the number of files in the pcap directory to 30000 to avoid limitations with the ext3 filesystem. However, if you're using the ext4 or xfs filesystems, then it is safe to increase this value. So if you have a large amount of storage and find that you only have 3 weeks worth of PCAP on disk while still having plenty of free space, then you may want to increase this default setting.
helpLink: stenographer.html
diskfreepercentage:
description: Stenographer will purge old PCAP on a regular basis to keep the disk free percentage at this level. If you have a distributed deployment with dedicated Sensor nodes, then the default value of 10 should be reasonable since Stenographer should be the main consumer of disk space in the /nsm partition. However, if you have systems that run both Stenographer and Elasticsearch at the same time (like eval and standalone installations), then youll want to make sure that this value is no lower than 21 so that you avoid Elasticsearch hitting its watermark setting at 80% disk usage. If you have an older standalone installation, then you may need to manually change this value to 21.
helpLink: stenographer.html
blocks:
description: The number of 1MB packet blocks used by Stenographer and AF_PACKET to store packets in memory, per thread. You shouldn't need to change this.
advanced: True
helpLink: stenographer.html
preallocate_file_mb:
description: File size to pre-allocate for individual Stenographer PCAP files. You shouldn't need to change this.
advanced: True
helpLink: stenographer.html
aiops:
description: The max number of async writes to allow for Stenographer at once.
advanced: True
helpLink: stenographer.html
pin_to_cpu:
description: Enable CPU pinning for Stenographer PCAP.
advanced: True
helpLink: stenographer.html
cpus_to_pin_to:
description: CPU to pin Stenographer PCAP to. Currently only a single CPU is supported.
advanced: True
helpLink: stenographer.html
disks:
description: List of disks to use for Stenographer PCAP. This is currently not used.
advanced: True
helpLink: stenographer.html

21
salt/pcap/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-steno_so-status.conf:
file.append:
- name: /opt/so/conf/so-status/so-status.conf
- text: so-steno
- unless: grep -q so-steno /opt/so/conf/so-status/so-status.conf
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

View File

@@ -0,0 +1,18 @@
#!/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 [ $# -lt 2 ]; then
echo "Usage: $0 <steno-query> Output-Filename"
exit 1
fi
docker exec -t so-sensoroni scripts/stenoquery.sh "$1" -w /nsm/pcapout/$2.pcap
echo ""
echo "If successful, the output was written to: /nsm/pcapout/$2.pcap"

View File

@@ -0,0 +1,12 @@
#!/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.
. /usr/sbin/so-common
/usr/sbin/so-restart steno $1

View File

@@ -0,0 +1,12 @@
#!/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.
. /usr/sbin/so-common
/usr/sbin/so-start steno $1

View File

@@ -0,0 +1,12 @@
#!/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.
. /usr/sbin/so-common
/usr/sbin/so-stop steno $1

View File

@@ -22,6 +22,18 @@ include:
{% endif %}
{% 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:

View File

@@ -8,6 +8,9 @@
include:
{% if GLOBALS.is_sensor or GLOBALS.role == 'so-import' %}
- pcap.ca
{% endif %}
- sensoroni.config
- sensoroni.sostatus
@@ -16,6 +19,10 @@ so-sensoroni:
- image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-soc:{{ GLOBALS.so_version }}
- network_mode: host
- binds:
{% if GLOBALS.is_sensor or GLOBALS.role == 'so-import' %}
- /opt/so/conf/steno/certs:/etc/stenographer/certs:rw
{% endif %}
- /nsm/pcap:/nsm/pcap:rw
- /nsm/import:/nsm/import:rw
- /nsm/pcapout:/nsm/pcapout:rw
- /opt/so/conf/sensoroni/sensoroni.json:/opt/sensoroni/sensoroni.json:ro

View File

@@ -14,7 +14,7 @@ An API key or User Credentials is necessary for utilizing Elasticsearch.
In SOC, navigate to `Administration`, toggle `Show all configurable settings, including advanced settings.`, and navigate to `sensoroni` -> `analyzers` -> `elasticsearch`.
![image](https://github.com/Security-Onion-Solutions/securityonion/blob/3/dev/assets/images/screenshots/analyzers/elasticsearch.png?raw=true)
![image](https://github.com/Security-Onion-Solutions/securityonion/blob/2.4/dev/assets/images/screenshots/analyzers/elasticsearch.png?raw=true)
The following configuration options are available for:

View File

@@ -6,7 +6,7 @@ Submit a base64-encoded EML file to Sublime Platform for analysis.
## Configuration Requirements
In SOC, navigate to `Administration`, toggle `Show all configurable settings, including advanced settings.`, and navigate to `sensoroni` -> `analyzers` -> `sublime_platform`.
![image](https://github.com/Security-Onion-Solutions/securityonion/blob/3/dev/assets/images/screenshots/analyzers/sublime.png?raw=true)
![image](https://github.com/Security-Onion-Solutions/securityonion/blob/2.4/dev/assets/images/screenshots/analyzers/sublime.png?raw=true)
The following configuration options are available for:

View File

@@ -32,6 +32,11 @@
"apiKey": "{{ GLOBALS.sensoroni_key }}"
{% if GLOBALS.is_sensor %}
},
"stenoquery": {
"executablePath": "/opt/sensoroni/scripts/stenoquery.sh",
"pcapInputPath": "/nsm/pcap",
"pcapOutputPath": "/nsm/pcapout"
},
"suriquery": {
"pcapInputPath": "/nsm/suripcap",
"pcapOutputPath": "/nsm/pcapout",

View File

@@ -10,7 +10,7 @@
{% from 'suricata/map.jinja' import SURICATAMERGED %}
{% from 'bpf/suricata.map.jinja' import SURICATABPF, SURICATA_BPF_STATUS, SURICATA_BPF_CALC %}
{% if GLOBALS.pcap_engine in ["SURICATA"] %}
{% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
{% from 'bpf/pcap.map.jinja' import PCAPBPF, PCAP_BPF_STATUS, PCAP_BPF_CALC %}
# BPF compilation and configuration
{% if PCAPBPF and not PCAP_BPF_STATUS %}

View File

@@ -1,7 +1,6 @@
suricata:
enabled: False
pcap:
enabled: "no"
filesize: 1000mb
maxsize: 25
compression: "none"
@@ -142,6 +141,8 @@ suricata:
enabled: "no"
tls-store:
enabled: "no"
pcap-log:
enabled: "no"
alert-debug:
enabled: "no"
alert-prelude:

View File

@@ -9,20 +9,21 @@
{% set surimeta_filestore_index = [] %}
{# before we change outputs back to list, enable pcap-log if suricata is the pcapengine #}
{% if GLOBALS.pcap_engine in ["SURICATA"] %}
{# initialize pcap-log in config.outputs since we dont put it in defaults #}
{% if 'pcap-log' not in SURICATAMERGED.config.outputs %}
{% do SURICATAMERGED.config.outputs.update({'pcap-log': {}}) %}
{% endif %}
{% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
{% from 'bpf/pcap.map.jinja' import PCAPBPF, PCAP_BPF_STATUS %}
{% if PCAPBPF and PCAP_BPF_STATUS %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'bpf-filter': PCAPBPF|join(" ")}) %}
{% endif %}
{% set PCAP = salt['pillar.get']('pcap', {'enabled': false}) %}
{% if PCAP.enabled and GLOBALS.role != 'so-import'%}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'enabled': 'yes'}) %}
{% else %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'enabled': 'no'}) %}
{% endif %}
{# move the items in suricata.pcap into suricata.config.outputs.pcap-log. these items were placed under suricata.config for ease of access in SOC #}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'enabled': SURICATAMERGED.pcap.enabled}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'compression': SURICATAMERGED.pcap.compression}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'lz4-checksum': SURICATAMERGED.pcap['lz4-checksum']}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'lz4-level': SURICATAMERGED.pcap['lz4-level']}) %}

View File

@@ -2,7 +2,7 @@
{% from 'suricata/map.jinja' import SURICATAMERGED %}
# This directory needs to exist regardless of whether SURIPCAP is enabled or not, in order for
# Sensoroni to mount it
# Sensoroni to be able to look at old Suricata PCAP data
suripcapdir:
file.directory:
- name: /nsm/suripcap
@@ -11,14 +11,7 @@ suripcapdir:
- mode: 775
- makedirs: True
pcapoutdir:
file.directory:
- name: /nsm/pcapout
- user: 939
- group: 939
- makedirs: True
{% if GLOBALS.pcap_engine in ["SURICATA"] %}
{% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
{# there should only be 1 interface in af-packet so we can just reference the first list item #}
{% for i in range(1, SURICATAMERGED.config['af-packet'][0].threads + 1) %}

View File

@@ -22,10 +22,6 @@ suricata:
title: Classifications
helpLink: suricata.html
pcap:
enabled:
description: Enables or disables the Suricata packet recording process.
forcedType: bool
helpLink: suricata.html
filesize:
description: Maximum file size for individual PCAP files written by Suricata. Increasing this number could improve write performance at the expense of pcap retrieval time.
advanced: True
@@ -213,6 +209,12 @@ suricata:
header:
description: Header name where the actual IP address will be reported.
helpLink: suricata.html
pcap-log:
enabled:
description: This value is ignored by SO. pcapengine in globals takes precedence.
readonly: True
helpLink: suricata.html
advanced: True
asn1-max-frames:
description: Maximum nuber of asn1 frames to decode.
helpLink: suricata.html

View File

@@ -31,9 +31,8 @@ mkdir -p /tmp/nids-testing/output
chown suricata:socore /tmp/nids-testing/output
mkdir -p /tmp/nids-testing/rules
cp /opt/so/rules/suricata/all-rulesets.rules /tmp/nids-testing/rules/all-rulesets.rules
cat $TESTRULE >> /tmp/nids-testing/rules/all-rulesets.rules
cp /opt/so/conf/suricata/rules/all.rules /tmp/nids-testing/rules/all.rules
cat $TESTRULE >> /tmp/nids-testing/rules/all.rules
echo "==== Begin Suricata Output ==="

View File

@@ -19,6 +19,7 @@ telegraf:
- os.sh
- raid.sh
- sostatus.sh
- stenoloss.sh
- suriloss.sh
- surirules.sh
- zeekcaptureloss.sh
@@ -34,6 +35,7 @@ telegraf:
- raid.sh
- redis.sh
- sostatus.sh
- stenoloss.sh
- suriloss.sh
- surirules.sh
- zeekcaptureloss.sh
@@ -79,6 +81,7 @@ telegraf:
- os.sh
- raid.sh
- sostatus.sh
- stenoloss.sh
- suriloss.sh
- surirules.sh
- zeekcaptureloss.sh
@@ -93,6 +96,7 @@ telegraf:
- raid.sh
- redis.sh
- sostatus.sh
- stenoloss.sh
- suriloss.sh
- surirules.sh
- zeekcaptureloss.sh

View File

@@ -47,6 +47,7 @@ so-telegraf:
- /etc/pki/telegraf.crt:/etc/telegraf/telegraf.crt:ro
- /etc/pki/telegraf.key:/etc/telegraf/telegraf.key:ro
- /opt/so/conf/telegraf/scripts:/scripts:ro
- /opt/so/log/stenographer:/var/log/stenographer:ro
- /opt/so/log/suricata:/var/log/suricata:ro
- /opt/so/log/raid:/var/log/raid:ro
- /opt/so/log/sostatus:/var/log/sostatus:ro

View File

@@ -14,6 +14,13 @@
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('zeekloss.sh') %}
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('zeekcaptureloss.sh') %}
{% endif %}
{% from 'pcap/config.map.jinja' import PCAPMERGED %}
{# PCAPMERGED.enabled is set false in soc ui or if suricata is the pcap engine #}
{% if not PCAPMERGED.enabled %}
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('stenoloss.sh') %}
{% endif %}
{% endif %}
{% if GLOBALS.pipeline != 'REDIS' %}

View File

@@ -5,7 +5,11 @@
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{%- if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
PCAPLOC=/host/nsm/suripcap
{%- else %}
PCAPLOC=/host/nsm/pcap
{%- endif %}
# if this script isn't already running
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then

View File

@@ -0,0 +1,39 @@
#!/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 this script isn't already running
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
CHECKIT=$(grep "Thread 0 stats" /var/log/stenographer/stenographer.log |tac |head -2|wc -l)
STENOGREP=$(grep "Thread 0 stats" /var/log/stenographer/stenographer.log |tac |head -2)
declare RESULT=($STENOGREP)
CURRENT_PACKETS=$(echo ${RESULT[9]} | awk -F'=' '{print $2 }')
CURRENT_DROPS=$(echo ${RESULT[12]} | awk -F'=' '{print $2 }')
PREVIOUS_PACKETS=$(echo ${RESULT[23]} | awk -F'=' '{print $2 }')
PREVIOUS_DROPS=$(echo ${RESULT[26]} | awk -F'=' '{print $2 }')
DROPPED=$((CURRENT_DROPS - PREVIOUS_DROPS))
TOTAL_CURRENT=$((CURRENT_PACKETS + CURRENT_DROPS))
TOTAL_PAST=$((PREVIOUS_PACKETS + PREVIOUS_DROPS))
TOTAL=$((TOTAL_CURRENT - TOTAL_PAST))
if [ $CHECKIT == 2 ]; then
if [ $DROPPED == 0 ]; then
echo "stenodrop drop=$DROPPED"
else
LOSS=$(echo "4 k $DROPPED $TOTAL / 100 * p" | dc)
echo "stenodrop drop=$LOSS"
fi
fi
fi
exit 0

View File

@@ -47,7 +47,7 @@ telegraf_key_perms:
- group: 939
{% if not GLOBALS.is_manager %}
{# Prior to 2.4.210, minions used influxdb.crt and key for telegraf #}
{# Prior to 2.4.220, minions used influxdb.crt and key for telegraf #}
remove_influxdb.crt:
file.absent:
- name: /etc/pki/influxdb.crt

View File

@@ -78,6 +78,7 @@ base:
- elasticsearch
- elastic-fleet-package-registry
- kibana
- pcap
- suricata
- zeek
- strelka
@@ -85,7 +86,6 @@ base:
- elastalert
- utility
- elasticfleet
- pcap.cleanup
'*_standalone and G@saltversion:{{saltversion}} and not I@node_data:False':
- match: compound
@@ -108,6 +108,7 @@ base:
- redis
- elastic-fleet-package-registry
- kibana
- pcap
- suricata
- zeek
- strelka
@@ -117,7 +118,6 @@ base:
- elasticfleet
- stig
- kafka
- pcap.cleanup
'*_manager or *_managerhype and G@saltversion:{{saltversion}} and not I@node_data:False':
- match: compound
@@ -192,6 +192,7 @@ base:
- sensoroni
- telegraf
- firewall
- pcap
- elasticsearch
- elastic-fleet-package-registry
- kibana
@@ -199,7 +200,6 @@ base:
- suricata
- zeek
- elasticfleet
- pcap.cleanup
'*_searchnode and G@saltversion:{{saltversion}}':
- match: compound
@@ -220,13 +220,13 @@ base:
- telegraf
- firewall
- nginx
- pcap
- suricata
- healthcheck
- zeek
- strelka
- elasticfleet.install_agent_grid
- stig
- pcap.cleanup
'*_heavynode and G@saltversion:{{saltversion}}':
- match: compound
@@ -240,11 +240,11 @@ base:
- redis
- curator.disabled
- strelka
- pcap
- suricata
- zeek
- elasticfleet.install_agent_grid
- elasticagent
- pcap.cleanup
'*_receiver and G@saltversion:{{saltversion}}':
- match: compound

View File

@@ -852,14 +852,74 @@ detect_cloud() {
detect_os() {
title "Detecting Base OS"
if [ -f /etc/redhat-release ] && grep -q "Red Hat Enterprise Linux release 9" /etc/redhat-release && [ -f /etc/oracle-release ]; then
OS=oracle
OSVER=9
is_oracle=true
is_rpm=true
is_supported=true
if [ -f /etc/redhat-release ]; then
if grep -q "Rocky Linux release 9" /etc/redhat-release; then
OS=rocky
OSVER=9
is_rocky=true
is_rpm=true
not_supported=true
unset is_supported
elif grep -q "CentOS Stream release 9" /etc/redhat-release; then
OS=centos
OSVER=9
is_centos=true
is_rpm=true
not_supported=true
unset is_supported
elif grep -q "AlmaLinux release 9" /etc/redhat-release; then
OS=alma
OSVER=9
is_alma=true
is_rpm=true
not_supported=true
unset is_supported
elif grep -q "Red Hat Enterprise Linux release 9" /etc/redhat-release; then
if [ -f /etc/oracle-release ]; then
OS=oracle
OSVER=9
is_oracle=true
is_rpm=true
is_supported=true
else
OS=rhel
OSVER=9
is_rhel=true
is_rpm=true
not_supported=true
unset is_supported
fi
fi
elif [ -f /etc/os-release ]; then
if grep -q "UBUNTU_CODENAME=focal" /etc/os-release; then
OSVER=focal
UBVER=20.04
OS=ubuntu
is_ubuntu=true
is_deb=true
not_supported=true
unset is_supported
elif grep -q "UBUNTU_CODENAME=jammy" /etc/os-release; then
OSVER=jammy
UBVER=22.04
OS=ubuntu
is_ubuntu=true
is_deb=true
not_supported=true
unset is_supported
elif grep -q "VERSION_CODENAME=bookworm" /etc/os-release; then
OSVER=bookworm
DEBVER=12
is_debian=true
OS=debian
is_deb=true
not_supported=true
unset is_supported
fi
installer_prereq_packages
else
info "This OS is not supported. Security Onion requires Oracle Linux 9."
info "We were unable to determine if you are using a supported OS."
fail_setup
fi
@@ -872,6 +932,23 @@ download_elastic_agent_artifacts() {
fi
}
installer_prereq_packages() {
if [[ $is_deb ]]; then
# Print message to stdout so the user knows setup is doing something
info "Running apt-get update"
retry 150 10 "apt-get update" "" "Err:" >> "$setup_log" 2>&1 || fail_setup
# Install network manager so we can do interface stuff
if ! command -v nmcli > /dev/null 2>&1; then
info "Installing network-manager"
retry 150 10 "apt-get -y install network-manager ethtool" >> "$setup_log" 2>&1 || fail_setup
logCmd "systemctl enable NetworkManager"
logCmd "systemctl start NetworkManager"
fi
if ! command -v curl > /dev/null 2>&1; then
retry 150 10 "apt-get -y install curl" >> "$setup_log" 2>&1 || fail_setup
fi
fi
}
disable_auto_start() {
@@ -1305,7 +1382,9 @@ create_global() {
echo " registry_host: '$HOSTNAME'" >> $global_pillar_file
echo " endgamehost: '$ENDGAMEHOST'" >> $global_pillar_file
echo " pcapengine: SURICATA" >> $global_pillar_file
if [[ $is_standalone || $is_eval ]]; then
echo " pcapengine: SURICATA" >> $global_pillar_file
fi
}
create_sensoroni_pillar() {
@@ -1367,7 +1446,7 @@ make_some_dirs() {
mkdir -p $local_salt_dir/salt/firewall/portgroups
mkdir -p $local_salt_dir/salt/firewall/ports
for THEDIR in bpf elasticsearch ntp firewall redis backup influxdb strelka sensoroni soc docker zeek suricata nginx telegraf logstash soc manager kratos hydra idh elastalert stig global kafka versionlock hypervisor vm; do
for THEDIR in bpf pcap elasticsearch ntp firewall redis backup influxdb strelka sensoroni soc docker zeek suricata nginx telegraf logstash soc manager kratos hydra idh elastalert stig global kafka versionlock hypervisor vm; do
mkdir -p $local_salt_dir/pillar/$THEDIR
touch $local_salt_dir/pillar/$THEDIR/adv_$THEDIR.sls
touch $local_salt_dir/pillar/$THEDIR/soc_$THEDIR.sls
@@ -1383,7 +1462,7 @@ network_init() {
title "Initializing Network"
disable_ipv6
set_hostname
if [[ ( $is_iso || $is_desktop_iso ) ]]; then
if [[ ( $is_iso || $is_desktop_iso || $is_debian ) ]]; then
set_management_interface
fi
}
@@ -1521,6 +1600,7 @@ reserve_group_ids() {
logCmd "groupadd -g 940 suricata"
logCmd "groupadd -g 948 elastic-agent-pr"
logCmd "groupadd -g 949 elastic-agent"
logCmd "groupadd -g 941 stenographer"
logCmd "groupadd -g 947 elastic-fleet"
logCmd "groupadd -g 960 kafka"
}
@@ -1617,6 +1697,11 @@ reinstall_init() {
# Uninstall local Elastic Agent, if installed
elastic-agent uninstall -f
if [[ $is_deb ]]; then
echo "Unholding previously held packages."
apt-mark unhold $(apt-mark showhold)
fi
} >> "$setup_log" 2>&1
info "System reinstall init has been completed."
@@ -1633,7 +1718,11 @@ reset_proxy() {
[[ -f /etc/gitconfig ]] && rm -f /etc/gitconfig
sed -i "/proxy=/d" /etc/dnf/dnf.conf
if [[ $is_rpm ]]; then
sed -i "/proxy=/d" /etc/dnf/dnf.conf
else
[[ -f /etc/apt/apt.conf.d/00-proxy.conf ]] && rm -f /etc/apt/apt.conf.d/00-proxy.conf
fi
}
restore_file() {
@@ -1679,8 +1768,14 @@ drop_install_options() {
remove_package() {
local package_name=$1
if rpm -qa | grep -q "$package_name"; then
logCmd "dnf remove -y $package_name"
if [[ $is_rpm ]]; then
if rpm -qa | grep -q "$package_name"; then
logCmd "dnf remove -y $package_name"
fi
else
if dpkg -l | grep -q "$package_name"; then
retry 150 10 "apt purge -y \"$package_name\""
fi
fi
}
@@ -1694,91 +1789,122 @@ remove_package() {
securityonion_repo() {
# Remove all the current repos
logCmd "dnf -v clean all"
logCmd "mkdir -vp /root/oldrepos"
if [ -n "$(ls -A /etc/yum.repos.d/ 2>/dev/null)" ]; then
logCmd "mv -v /etc/yum.repos.d/* /root/oldrepos/"
fi
if ! $is_desktop_grid; then
gpg_rpm_import
if [[ ! $is_airgap ]]; then
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9" > /etc/yum/mirror.txt
echo "https://so-repo-east.s3.us-east-005.backblazeb2.com/prod/3/oracle/9" >> /etc/yum/mirror.txt
echo "[main]" > /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
echo "installonly_limit=3" >> /etc/yum.repos.d/securityonion.repo
echo "clean_requirements_on_remove=True" >> /etc/yum.repos.d/securityonion.repo
echo "best=True" >> /etc/yum.repos.d/securityonion.repo
echo "skip_if_unavailable=False" >> /etc/yum.repos.d/securityonion.repo
echo "cachedir=/opt/so/conf/reposync/cache" >> /etc/yum.repos.d/securityonion.repo
echo "keepcache=0" >> /etc/yum.repos.d/securityonion.repo
echo "[securityonionsync]" >> /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo repo" >> /etc/yum.repos.d/securityonion.repo
echo "mirrorlist=file:///etc/yum/mirror.txt" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
logCmd "dnf repolist"
else
if [[ $is_oracle ]]; then
logCmd "dnf -v clean all"
logCmd "mkdir -vp /root/oldrepos"
if [ -n "$(ls -A /etc/yum.repos.d/ 2>/dev/null)" ]; then
logCmd "mv -v /etc/yum.repos.d/* /root/oldrepos/"
fi
if ! $is_desktop_grid; then
gpg_rpm_import
if [[ ! $is_airgap ]]; then
echo "https://repo.securityonion.net/file/so-repo/prod/2.4/oracle/9" > /etc/yum/mirror.txt
echo "https://so-repo-east.s3.us-east-005.backblazeb2.com/prod/2.4/oracle/9" >> /etc/yum/mirror.txt
echo "[main]" > /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
echo "installonly_limit=3" >> /etc/yum.repos.d/securityonion.repo
echo "clean_requirements_on_remove=True" >> /etc/yum.repos.d/securityonion.repo
echo "best=True" >> /etc/yum.repos.d/securityonion.repo
echo "skip_if_unavailable=False" >> /etc/yum.repos.d/securityonion.repo
echo "cachedir=/opt/so/conf/reposync/cache" >> /etc/yum.repos.d/securityonion.repo
echo "keepcache=0" >> /etc/yum.repos.d/securityonion.repo
echo "[securityonionsync]" >> /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo repo" >> /etc/yum.repos.d/securityonion.repo
echo "mirrorlist=file:///etc/yum/mirror.txt" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
logCmd "dnf repolist"
else
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
echo "baseurl=https://$MSRV/repo" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
logCmd "dnf repolist"
fi
elif [[ ! $waitforstate ]]; then
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
echo "baseurl=https://$MSRV/repo" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
logCmd "dnf repolist"
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
elif [[ $waitforstate ]]; then
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
echo "baseurl=file:///nsm/repo/" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
fi
elif [[ ! $waitforstate ]]; then
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
echo "baseurl=https://$MSRV/repo" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
echo "sslverify=0" >> /etc/yum.repos.d/securityonion.repo
elif [[ $waitforstate ]]; then
echo "[securityonion]" > /etc/yum.repos.d/securityonion.repo
echo "name=Security Onion Repo" >> /etc/yum.repos.d/securityonion.repo
echo "baseurl=file:///nsm/repo/" >> /etc/yum.repos.d/securityonion.repo
echo "enabled=1" >> /etc/yum.repos.d/securityonion.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/securityonion.repo
fi
logCmd "dnf repolist all"
if [[ $is_rpm ]]; then logCmd "dnf repolist all"; fi
if [[ $waitforstate ]]; then
# Build the repo locally so we can use it
echo "Syncing Repos"
repo_sync_local
if [[ $is_rpm ]]; then
# Build the repo locally so we can use it
echo "Syncing Repos"
repo_sync_local
fi
fi
}
repo_sync_local() {
SALTVERSION=$(grep "version:" ../salt/salt/master.defaults.yaml | grep -o "[0-9]\+\.[0-9]\+")
info "Repo Sync"
# Sync the repo from the SO repo locally.
info "Adding Repo Download Configuration"
mkdir -p /nsm/repo
mkdir -p /opt/so/conf/reposync/cache
echo "https://repo.securityonion.net/file/so-repo/prod/3/oracle/9" > /opt/so/conf/reposync/mirror.txt
echo "https://repo-alt.securityonion.net/prod/3/oracle/9" >> /opt/so/conf/reposync/mirror.txt
echo "[main]" > /opt/so/conf/reposync/repodownload.conf
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf
echo "clean_requirements_on_remove=True" >> /opt/so/conf/reposync/repodownload.conf
echo "best=True" >> /opt/so/conf/reposync/repodownload.conf
echo "skip_if_unavailable=False" >> /opt/so/conf/reposync/repodownload.conf
echo "cachedir=/opt/so/conf/reposync/cache" >> /opt/so/conf/reposync/repodownload.conf
echo "keepcache=0" >> /opt/so/conf/reposync/repodownload.conf
echo "[securityonionsync]" >> /opt/so/conf/reposync/repodownload.conf
echo "name=Security Onion Repo repo" >> /opt/so/conf/reposync/repodownload.conf
echo "mirrorlist=file:///opt/so/conf/reposync/mirror.txt" >> /opt/so/conf/reposync/repodownload.conf
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
logCmd "dnf repolist"
if [[ ! $is_airgap ]]; then
curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/" >> "$setup_log" 2>&1 || fail_setup
# After the download is complete run createrepo
create_repo
if [[ $is_supported ]]; then
# Sync the repo from the the SO repo locally.
# Check for reposync
info "Adding Repo Download Configuration"
mkdir -p /nsm/repo
mkdir -p /opt/so/conf/reposync/cache
echo "https://repo.securityonion.net/file/so-repo/prod/2.4/oracle/9" > /opt/so/conf/reposync/mirror.txt
echo "https://repo-alt.securityonion.net/prod/2.4/oracle/9" >> /opt/so/conf/reposync/mirror.txt
echo "[main]" > /opt/so/conf/reposync/repodownload.conf
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf
echo "clean_requirements_on_remove=True" >> /opt/so/conf/reposync/repodownload.conf
echo "best=True" >> /opt/so/conf/reposync/repodownload.conf
echo "skip_if_unavailable=False" >> /opt/so/conf/reposync/repodownload.conf
echo "cachedir=/opt/so/conf/reposync/cache" >> /opt/so/conf/reposync/repodownload.conf
echo "keepcache=0" >> /opt/so/conf/reposync/repodownload.conf
echo "[securityonionsync]" >> /opt/so/conf/reposync/repodownload.conf
echo "name=Security Onion Repo repo" >> /opt/so/conf/reposync/repodownload.conf
echo "mirrorlist=file:///opt/so/conf/reposync/mirror.txt" >> /opt/so/conf/reposync/repodownload.conf
echo "enabled=1" >> /opt/so/conf/reposync/repodownload.conf
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
logCmd "dnf repolist"
if [[ ! $is_airgap ]]; then
curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install
retry 5 60 "dnf reposync --norepopath -g --delete -m -c /opt/so/conf/reposync/repodownload.conf --repoid=securityonionsync --download-metadata -p /nsm/repo/" >> "$setup_log" 2>&1 || fail_setup
# After the download is complete run createrepo
create_repo
fi
else
# Add the proper repos for unsupported stuff
echo "Adding Repos"
if [[ $is_rpm ]]; then
if [[ $is_rhel ]]; then
logCmd "subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms"
info "Install epel for rhel"
logCmd "dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm"
logCmd "dnf -y install https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm"
else
logCmd "dnf config-manager --set-enabled crb"
logCmd "dnf -y install epel-release"
fi
dnf install -y yum-utils device-mapper-persistent-data lvm2
curl -fsSL https://repo.securityonion.net/file/so-repo/prod/2.4/so/so.repo | tee /etc/yum.repos.d/so.repo
rpm --import https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
curl -fsSL "https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.repo" | tee /etc/yum.repos.d/salt.repo
dnf repolist
curl --retry 5 --retry-delay 60 -A "netinstall/$SOVERSION/$OS/$(uname -r)/1" https://sigs.securityonion.net/checkup --output /tmp/install
else
echo "Not sure how you got here."
exit 1
fi
fi
}
@@ -1786,13 +1912,57 @@ saltify() {
SALTVERSION=$(grep "version:" ../salt/salt/master.defaults.yaml | grep -o "[0-9]\+\.[0-9]\+")
info "Installing Salt $SALTVERSION"
chmod u+x ../salt/salt/scripts/bootstrap-salt.sh
if [[ $is_deb ]]; then
if [[ $waitforstate ]]; then
# install all for a manager
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -M -X stable $SALTVERSION" || fail_setup
else
# just a minion
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -X stable $SALTVERSION" || fail_setup
DEBIAN_FRONTEND=noninteractive retry 30 10 "apt-get -y -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" upgrade" >> "$setup_log" 2>&1 || fail_setup
if [ $OSVER == "focal" ]; then update-alternatives --install /usr/bin/python python /usr/bin/python3.10 10; fi
local pkg_arr=(
'apache2-utils'
'ca-certificates'
'curl'
'software-properties-common'
'apt-transport-https'
'openssl'
'netcat-openbsd'
'jq'
'gnupg'
)
retry 30 10 "apt-get -y install ${pkg_arr[*]}" || fail_setup
logCmd "mkdir -vp /etc/apt/keyrings"
logCmd "wget -q --inet4-only -O /etc/apt/keyrings/docker.pub https://download.docker.com/linux/ubuntu/gpg"
if [[ $is_ubuntu ]]; then
# Add Docker Repo
add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
else
# Add Docker Repo
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $OSVER stable" > /etc/apt/sources.list.d/docker.list
fi
logCmd "apt-key add /etc/apt/keyrings/docker.pub"
retry 30 10 "apt-get update" "" "Err:" || fail_setup
if [[ $waitforstate ]]; then
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -M -X stable $SALTVERSION" || fail_setup
retry 30 10 "apt-mark hold salt-minion salt-common salt-master" || fail_setup
retry 30 10 "apt-get -y install python3-pip python3-dateutil python3-m2crypto python3-packaging python3-influxdb python3-lxml" || exit 1
else
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -X stable $SALTVERSION" || fail_setup
retry 30 10 "apt-mark hold salt-minion salt-common" || fail_setup
fi
fi
if [[ $is_rpm ]]; then
if [[ $waitforstate ]]; then
# install all for a manager
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -M -X stable $SALTVERSION" || fail_setup
else
# just a minion
retry 30 10 "bash ../salt/salt/scripts/bootstrap-salt.sh -r -X stable $SALTVERSION" || fail_setup
fi
fi
salt_install_module_deps
@@ -1938,7 +2108,14 @@ set_proxy() {
"}" > /root/.docker/config.json
# Set proxy for package manager
echo "proxy=$so_proxy" >> /etc/yum.conf
if [[ $is_rpm ]]; then
echo "proxy=$so_proxy" >> /etc/yum.conf
else
# Set it up so the updates roll through the manager
printf '%s\n'\
"Acquire::http::Proxy \"$so_proxy\";"\
"Acquire::https::Proxy \"$so_proxy\";" > /etc/apt/apt.conf.d/00-proxy.conf
fi
# Set global git proxy
printf '%s\n'\
@@ -2128,13 +2305,23 @@ update_sudoers_for_testing() {
}
update_packages() {
logCmd "dnf repolist"
logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*"
RMREPOFILES=("oracle-linux-ol9.repo" "uek-ol9.repo" "virt-ol9.repo")
info "Removing repo files added by oracle-repos package update"
for FILE in ${RMREPOFILES[@]}; do
logCmd "rm -f /etc/yum.repos.d/$FILE"
done
if [[ $is_oracle ]]; then
logCmd "dnf repolist"
logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*"
RMREPOFILES=("oracle-linux-ol9.repo" "uek-ol9.repo" "virt-ol9.repo")
info "Removing repo files added by oracle-repos package update"
for FILE in ${RMREPOFILES[@]}; do
logCmd "rm -f /etc/yum.repos.d/$FILE"
done
elif [[ $is_deb ]]; then
info "Running apt-get update"
retry 150 10 "apt-get -y update" "" "Err:" >> "$setup_log" 2>&1 || fail_setup
info "Running apt-get upgrade"
retry 150 10 "apt-get -y upgrade" >> "$setup_log" 2>&1 || fail_setup
else
info "Updating packages"
logCmd "dnf -y update --allowerasing --exclude=salt*,docker*,containerd*"
fi
}
# This is used for development to speed up network install tests.
@@ -2144,7 +2331,15 @@ use_turbo_proxy() {
return
fi
printf '%s\n' "proxy=${TURBO}:3142" >> /etc/yum.conf
if [[ $OS == 'centos' ]]; then
printf '%s\n' "proxy=${TURBO}:3142" >> /etc/yum.conf
else
printf '%s\n'\
"Acquire {"\
" HTTP::proxy \"${TURBO}:3142\";"\
" HTTPS::proxy \"${TURBO}:3142\";"\
"}" > /etc/apt/apt.conf.d/proxy.conf
fi
}
wait_for_file() {

View File

@@ -34,19 +34,32 @@ check_default_repos() {
printf '%s' "$repo_str" | tee -a "$preflight_log"
fi
if [[ $script_run == true ]]; then
printf '%s' 'yum update.'
if [[ $OS == 'centos' ]]; then
if [[ $script_run == true ]]; then
printf '%s' 'yum update.'
else
printf '%s' 'yum update.' | tee -a "$preflight_log"
fi
echo "" >> "$preflight_log"
yum -y check-update >> $preflight_log 2>&1
ret_code=$?
if [[ $ret_code == 0 || $ret_code == 100 ]]; then
printf '%s\n' ' SUCCESS'
ret_code=0
else
printf '%s\n' ' FAILURE'
fi
else
printf '%s' 'yum update.' | tee -a "$preflight_log"
fi
echo "" >> "$preflight_log"
yum -y check-update >> $preflight_log 2>&1
ret_code=$?
if [[ $ret_code == 0 || $ret_code == 100 ]]; then
printf '%s\n' ' SUCCESS'
ret_code=0
else
printf '%s\n' ' FAILURE'
if [[ $script_run == true ]]; then
printf '%s' 'apt update.'
else
printf '%s' 'apt update.' | tee -a "$preflight_log"
fi
echo "" >> "$preflight_log"
retry 150 10 "apt-get -y update" >> $preflight_log 2>&1
ret_code=$?
[[ $ret_code == 0 ]] && printf '%s\n' ' SUCCESS' || printf '%s\n' ' FAILURE'
fi
return $ret_code
@@ -60,11 +73,21 @@ check_new_repos() {
printf '%s' "$repo_url_str" | tee -a "$preflight_log"
fi
local repo_arr=(
"https://download.docker.com/linux/centos/docker-ce.repo"
"https://repo.securityonion.net/file/securityonion-repo/keys/SALTSTACK-GPG-KEY.pub"
"https://download.docker.com/linux/ubuntu/gpg"
if [[ $OS == 'centos' ]]; then
local repo_arr=(
"https://download.docker.com/linux/centos/docker-ce.repo"
"https://repo.securityonion.net/file/securityonion-repo/keys/SALTSTACK-GPG-KEY.pub"
"https://download.docker.com/linux/ubuntu/gpg"
)
else
local ubuntu_version
ubuntu_version=$(grep VERSION_ID /etc/os-release 2> /dev/null | awk -F '[ "]' '{print $2}')
local repo_arr=(
"https://download.docker.com/linux/ubuntu/gpg"
"https://download.docker.com/linux/ubuntu"
"https://repo.securityonion.net/file/securityonion-repo/ubuntu/$ubuntu_version/amd64/salt/SALTSTACK-GPG-KEY.pub"
)
fi
__check_url_arr "${repo_arr[@]}"
local ret_code=$?
@@ -132,6 +155,17 @@ __check_url_arr() {
return $ret_code
}
preflight_prereqs() {
local ret_code=0
if [[ $OS == 'centos' ]]; then
: # no-op to match structure of other checks for $OS var
else
retry 150 10 "apt-get -y install curl" >> "$preflight_log" 2>&1 || ret_code=1
fi
return $ret_code
}
main() {
local intro_str="Beginning pre-flight checks."
@@ -149,6 +183,7 @@ main() {
fi
check_default_repos &&\
preflight_prereqs &&\
check_new_repos &&\
check_misc_urls

View File

@@ -66,6 +66,36 @@ set_timezone
# Let's see what OS we are dealing with here
detect_os
# Ubuntu/Debian whiptail pallete to make it look the same as CentOS and Rocky.
set_palette >> $setup_log 2>&1
if [[ $not_supported ]] && [ -z "$test_profile" ]; then
if [[ "$OSVER" == "focal" ]]; then
if (whiptail_focal_warning); then
true
else
info "User cancelled setup."
whiptail_cancel
fi
else
if (whiptail_unsupported_os_warning); then
true
else
info "User cancelled setup."
whiptail_cancel
fi
fi
fi
# we need to upgrade packages on debian prior to install and reboot if there are due to iptables-restore not running properly
# if packages are updated and the box isn't rebooted
if [[ $is_debian ]]; then
update_packages
if [[ -f "/var/run/reboot-required" ]] && [ -z "$test_profile" ]; then
whiptail_debian_reboot_required
reboot
fi
fi
# Check to see if this is the setup type of "desktop".
is_desktop=
@@ -78,7 +108,7 @@ if [ "$setup_type" = 'desktop' ]; then
fi
fi
# Make sure if ISO is specified that we are dealing with an RPM-based install
# Make sure if ISO is specified that we are dealing with CentOS or Rocky
title "Detecting if this is an ISO install"
if [[ "$setup_type" == 'iso' ]]; then
if [[ $is_rpm ]]; then

View File

@@ -27,6 +27,23 @@ whiptail_airgap() {
fi
}
whiptail_debian_reboot_required() {
[ -n "$TESTING" ] && return
read -r -d '' message <<- EOM
Packages were upgraded and a reboot is required prior to Security Onion installation.
Once the reboot has completed, rerun Security Onion setup.
Press TAB and then the ENTER key to reboot the system.
EOM
whiptail --title "$whiptail_title" --msgbox "$message" 24 75 --scrolltext
}
whiptail_desktop_install() {
[ -n "$TESTING" ] && return
@@ -479,6 +496,27 @@ __append_end_msg() {
EOM
}
whiptail_focal_warning() {
[ -n "$TESTING" ] && return
read -r -d '' focal_warning_continue <<- EOM
WARNING: Ubuntu 20.04 is only supported as a minion role.
This node may not install or operate as expected if installed
as a manager, managersearch, standalone, eval, or import.
Would you like to continue the install?
EOM
whiptail --title "$whiptail_title" \
--yesno "$focal_warning_continue" 14 75 --defaultno
local exitstatus=$?
return $exitstatus
}
whiptail_gauge_post_setup() {
@@ -548,15 +586,23 @@ whiptail_install_type() {
[ -n "$TESTING" ] && return
# What kind of install are we doing?
install_type=$(whiptail --title "$whiptail_title" --menu \
"What kind of installation would you like to do?\n\nFor more information, please see:\n$DOC_BASE_URL/architecture" 18 65 5 \
"IMPORT" "Import PCAP or log files " \
"EVAL" "Evaluation mode (not for production) " \
"STANDALONE" "Standalone production install " \
"DISTRIBUTED" "Distributed deployment " \
"DESKTOP" "Security Onion Desktop" \
3>&1 1>&2 2>&3
)
if [[ "$OSVER" != "focal" ]]; then
install_type=$(whiptail --title "$whiptail_title" --menu \
"What kind of installation would you like to do?\n\nFor more information, please see:\n$DOC_BASE_URL/architecture" 18 65 5 \
"IMPORT" "Import PCAP or log files " \
"EVAL" "Evaluation mode (not for production) " \
"STANDALONE" "Standalone production install " \
"DISTRIBUTED" "Distributed deployment " \
"DESKTOP" "Security Onion Desktop" \
3>&1 1>&2 2>&3
)
elif [[ "$OSVER" == "focal" ]]; then
install_type=$(whiptail --title "$whiptail_title" --menu \
"What kind of installation would you like to do?\n\nFor more information, please see:\n$DOC_BASE_URL/architecture" 18 65 5 \
"DISTRIBUTED" "Distributed install submenu " \
3>&1 1>&2 2>&3
)
fi
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
@@ -577,11 +623,18 @@ whiptail_install_type_dist() {
[ -n "$TESTING" ] && return
if [[ "$OSVER" != "focal" ]]; then
dist_option=$(whiptail --title "$whiptail_title" --menu "Do you want to start a new deployment or join this box to \nan existing deployment?" 11 75 2 \
"New Deployment " "Create a new Security Onion deployment" \
"Existing Deployment " "Join to an existing Security Onion deployment " \
3>&1 1>&2 2>&3
)
elif [[ "$OSVER" == "focal" ]]; then
dist_option=$(whiptail --title "$whiptail_title" --menu "Since this is Ubuntu, this box can only be connected to \nan existing deployment." 11 75 2 \
"Existing Deployment " "Join to an existing Security Onion deployment " \
3>&1 1>&2 2>&3
)
fi
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
@@ -863,7 +916,7 @@ whiptail_net_method() {
[ -n "$TESTING" ] && return
local pkg_mngr
pkg_mngr="yum"
if [[ $OS = 'centos' ]]; then pkg_mngr="yum"; else pkg_mngr='apt'; fi
read -r -d '' options_msg <<- EOM
"Direct" - Internet requests connect directly to the Internet.
@@ -1098,7 +1151,7 @@ whiptail_proxy_ask() {
[ -n "$TESTING" ] && return
local pkg_mngr
pkg_mngr="yum"
if [[ $OS = 'centos' ]]; then pkg_mngr="yum"; else pkg_mngr='apt'; fi
whiptail --title "$whiptail_title" --yesno "Do you want to proxy the traffic for git, docker client, wget, curl, ${pkg_mngr}, and various other SO components through a separate server in your environment?" 9 65 --defaultno
}
@@ -1381,6 +1434,48 @@ whiptail_storage_requirements() {
whiptail_check_exitstatus $exitstatus
}
whiptail_ubuntu_notsupported() {
[ -n "$TESTING" ] && return
read -r -d '' message <<- EOM
Ubuntu is not supported for this node type.
Please use a supported OS or install via ISO.
EOM
whiptail --title "$whiptail_title" --msgbox "$message" 14 75
}
whiptail_ubuntu_warning() {
[ -n "$TESTING" ] && return
read -r -d '' message <<- EOM
Ubuntu support for this node type is limited.
Please consider using a fully supported OS or install via ISO.
EOM
whiptail --title "$whiptail_title" --msgbox "$message" 14 75
}
whiptail_unsupported_os_warning() {
[ -n "$TESTING" ] && return
read -r -d '' unsupported_os_continue <<- EOM
WARNING: An unsupported operating system has been detected.
Security Onion may not install or operate as expected.
Would you like to continue the install?
EOM
whiptail --title "$whiptail_title" \
--yesno "$unsupported_os_continue" 14 75 --defaultno
local exitstatus=$?
return $exitstatus
}
whiptail_uppercase_warning() {

Binary file not shown.