mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-01-24 17:03:27 +01:00
Compare commits
367 Commits
2.4.190-20
...
reyesj2/pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55b3fa389e | ||
|
|
b3ae716929 | ||
|
|
30d8cf5a6c | ||
|
|
07dbdb9f8f | ||
|
|
b4c8f7924a | ||
|
|
809422c517 | ||
|
|
bb7593a53a | ||
|
|
8e3ba8900f | ||
|
|
005ec87248 | ||
|
|
4c6ff0641b | ||
|
|
3e242913e9 | ||
|
|
ba68e3c9bd | ||
|
|
e1199a91b9 | ||
|
|
d381248e30 | ||
|
|
f4f0218cae | ||
|
|
7a38e52b01 | ||
|
|
959fd55e32 | ||
|
|
a8e218a9ff | ||
|
|
3f5cd46d7d | ||
|
|
627f0c2bcc | ||
|
|
f6bde3eb04 | ||
|
|
f6e95c17a0 | ||
|
|
1234cbd04b | ||
|
|
fd5b93542e | ||
|
|
a192455fae | ||
|
|
66f17e95aa | ||
|
|
6f4b96b61b | ||
|
|
9905d23976 | ||
|
|
17532fe49d | ||
|
|
074158b495 | ||
|
|
82d5115b3f | ||
|
|
5c63111002 | ||
|
|
6eda7932e8 | ||
|
|
399b7567dd | ||
|
|
2133ada3a1 | ||
|
|
4f6d4738c4 | ||
|
|
d430ed6727 | ||
|
|
596bc178df | ||
|
|
0cd3d7b5a8 | ||
|
|
349d77ffdf | ||
|
|
c3283b04e5 | ||
|
|
0da0788e6b | ||
|
|
6f7e249aa2 | ||
|
|
dfaeed54b6 | ||
|
|
4f59e46235 | ||
|
|
bf4cc7befb | ||
|
|
c63c6dc68b | ||
|
|
e4225d6e9b | ||
|
|
3fb153c43e | ||
|
|
6de20c63d4 | ||
|
|
00fbc1c259 | ||
|
|
3bc552ef38 | ||
|
|
ee70d94e15 | ||
|
|
1887d2c0e9 | ||
|
|
c99dd4e44f | ||
|
|
541b8b288d | ||
|
|
db168a0452 | ||
|
|
aa96cf44d4 | ||
|
|
0d59c35d2a | ||
|
|
8463bde90d | ||
|
|
150c31009e | ||
|
|
693494024d | ||
|
|
ee66d6c7d1 | ||
|
|
3effd30f7e | ||
|
|
4ab20c2454 | ||
|
|
c075b5a1a7 | ||
|
|
cb1e59fa49 | ||
|
|
588aa435ec | ||
|
|
752c764066 | ||
|
|
af604c2ea8 | ||
|
|
6c3f9f149d | ||
|
|
152f2e03f1 | ||
|
|
605797c86a | ||
|
|
1ee5b1611a | ||
|
|
5028729e4c | ||
|
|
ab00fa8809 | ||
|
|
2d705e7caa | ||
|
|
f2370043a8 | ||
|
|
3b349b9803 | ||
|
|
f2b7ffe0eb | ||
|
|
3a410eed1a | ||
|
|
a53619f10f | ||
|
|
893aaafa1b | ||
|
|
33c34cdeca | ||
|
|
9b411867df | ||
|
|
fd1596b3a0 | ||
|
|
b05de22f58 | ||
|
|
e9341ee8d3 | ||
|
|
f666ad600f | ||
|
|
9345718967 | ||
|
|
6c879cbd13 | ||
|
|
089b5aaf44 | ||
|
|
b61885add5 | ||
|
|
702ba2e0a4 | ||
|
|
5cb1e284af | ||
|
|
e3a4f0873e | ||
|
|
7977a020ac | ||
|
|
1d63269883 | ||
|
|
dd8027480b | ||
|
|
c45bd77e44 | ||
|
|
032e0abd61 | ||
|
|
8509d1e454 | ||
|
|
8ff0c6828b | ||
|
|
ddd6935e50 | ||
|
|
5588a56b24 | ||
|
|
12aed6e280 | ||
|
|
b2a469e08c | ||
|
|
285b0e4af9 | ||
|
|
f9edfd6391 | ||
|
|
c0845e1612 | ||
|
|
9878d9d37e | ||
|
|
a2196085d5 | ||
|
|
ba62a8c10c | ||
|
|
38f38e2789 | ||
|
|
1475f0fc2f | ||
|
|
a3396b77a3 | ||
|
|
8158fee8fc | ||
|
|
f6301bc3e5 | ||
|
|
6c5c176b7d | ||
|
|
c6d52b5eb1 | ||
|
|
7cac528389 | ||
|
|
d518f75468 | ||
|
|
c6fac8c36b | ||
|
|
17b5b81696 | ||
|
|
9960db200c | ||
|
|
b9ff1704b0 | ||
|
|
6fe817ca4a | ||
|
|
cb9a6fac25 | ||
|
|
a945768251 | ||
|
|
c6646e3821 | ||
|
|
99dc72cece | ||
|
|
04d6cca204 | ||
|
|
5ab6bda639 | ||
|
|
f433de7e12 | ||
|
|
8ef6c2f91d | ||
|
|
7575218697 | ||
|
|
dc945dad00 | ||
|
|
ddcd74ffd2 | ||
|
|
e105bd12e6 | ||
|
|
f5688175b6 | ||
|
|
72a4ba405f | ||
|
|
94694d394e | ||
|
|
03dd746601 | ||
|
|
eec3373ae7 | ||
|
|
db45ce07ed | ||
|
|
ba49765312 | ||
|
|
72c8c2371e | ||
|
|
80411ab6cf | ||
|
|
0ff8fa57e7 | ||
|
|
411f28a049 | ||
|
|
0f42233092 | ||
|
|
2dd49f6d9b | ||
|
|
271f545f4f | ||
|
|
c4a70b540e | ||
|
|
bef85772e3 | ||
|
|
a6b19c4a6c | ||
|
|
44f5e6659b | ||
|
|
3f9a9b7019 | ||
|
|
b7ad985c7a | ||
|
|
dba087ae25 | ||
|
|
bbc4b1b502 | ||
|
|
9304513ce8 | ||
|
|
0b127582cb | ||
|
|
6e9b8791c8 | ||
|
|
ef87ad77c3 | ||
|
|
8477420911 | ||
|
|
f5741e318f | ||
|
|
545060103a | ||
|
|
e010b5680a | ||
|
|
8620d3987e | ||
|
|
30487a54c1 | ||
|
|
f15a39c153 | ||
|
|
aed27fa111 | ||
|
|
822c411e83 | ||
|
|
41b3ac7554 | ||
|
|
23575fdf6c | ||
|
|
52f70dc49a | ||
|
|
79c9749ff7 | ||
|
|
8d2701e143 | ||
|
|
877444ac29 | ||
|
|
b0d9426f1b | ||
|
|
18accae47e | ||
|
|
55e3a2c6b6 | ||
|
|
ef092e2893 | ||
|
|
89eb95c077 | ||
|
|
e871ec358e | ||
|
|
271a2f74ad | ||
|
|
d6bd951c37 | ||
|
|
8abd4c9c78 | ||
|
|
45a8c0acd1 | ||
|
|
c372cd533d | ||
|
|
999f83ce57 | ||
|
|
6fbed2dd9f | ||
|
|
36a6a59d55 | ||
|
|
875de88cb4 | ||
|
|
63bb44886e | ||
|
|
bda83a47a2 | ||
|
|
e96cfd35f7 | ||
|
|
65c96b2edf | ||
|
|
87477ae4f6 | ||
|
|
89a9106d79 | ||
|
|
1284150382 | ||
|
|
edf3c9464f | ||
|
|
4bb0a7c9d9 | ||
|
|
ced3af818c | ||
|
|
cc8fb96047 | ||
|
|
3339b50daf | ||
|
|
415ea07a4f | ||
|
|
b80ec95fa8 | ||
|
|
99cb51482f | ||
|
|
90638f7a43 | ||
|
|
1fb00c8eb6 | ||
|
|
4490ea7635 | ||
|
|
bce7a20d8b | ||
|
|
9c06713f32 | ||
|
|
23da0d4ba0 | ||
|
|
d5f2cfb354 | ||
|
|
fb5ad4193d | ||
|
|
1f5f283c06 | ||
|
|
cf048030c4 | ||
|
|
2d716b44a8 | ||
|
|
d70d652310 | ||
|
|
c5db7c8752 | ||
|
|
6f42ff3442 | ||
|
|
433dab7376 | ||
|
|
97c1a46013 | ||
|
|
fbe97221bb | ||
|
|
841ce6b6ec | ||
|
|
dd0b4c3820 | ||
|
|
b52dd53e29 | ||
|
|
a155f45036 | ||
|
|
b407c68d88 | ||
|
|
5b6a7035af | ||
|
|
12d490ad4a | ||
|
|
76cbd18d2c | ||
|
|
148ef7ef21 | ||
|
|
1b55642c86 | ||
|
|
af7f7d0728 | ||
|
|
a7337c95e1 | ||
|
|
3f7c3326ea | ||
|
|
bf41de8c14 | ||
|
|
de4424fab0 | ||
|
|
136a829509 | ||
|
|
bcec999be4 | ||
|
|
7c73b4713f | ||
|
|
45b4b1d963 | ||
|
|
fcfd74ec1e | ||
|
|
68b0cd7549 | ||
|
|
715d801ce8 | ||
|
|
4a810696e7 | ||
|
|
6b525a2c21 | ||
|
|
a5d8385f07 | ||
|
|
211bf7e77b | ||
|
|
1542b74133 | ||
|
|
431e5abf89 | ||
|
|
4314c79f85 | ||
|
|
da9717bc79 | ||
|
|
f047677d8a | ||
|
|
045cf7866c | ||
|
|
431e0b0780 | ||
|
|
e782266caa | ||
|
|
a4666b2c08 | ||
|
|
dcc3206e51 | ||
|
|
8358b6ea6f | ||
|
|
d1a66a91c6 | ||
|
|
7fdcb92614 | ||
|
|
cec1890b6b | ||
|
|
b2606b6094 | ||
|
|
b1b66045ea | ||
|
|
33b22bf2e4 | ||
|
|
3a38886345 | ||
|
|
7be70faab6 | ||
|
|
2729fdbea6 | ||
|
|
bfd08d1d2e | ||
|
|
37b3fd9b7b | ||
|
|
573dded921 | ||
|
|
fed75c7b39 | ||
|
|
3427df2a54 | ||
|
|
be11c718f6 | ||
|
|
235dfd78f1 | ||
|
|
7c8b9b4374 | ||
|
|
81d7c313af | ||
|
|
9a6ff75793 | ||
|
|
1f24796eba | ||
|
|
7762faf075 | ||
|
|
80fbb31372 | ||
|
|
7c45db2295 | ||
|
|
0545e1d33b | ||
|
|
55bbbdb58d | ||
|
|
3a8a6bf5ff | ||
|
|
13789bc56f | ||
|
|
11518f6eea | ||
|
|
08147e27b0 | ||
|
|
c9153617be | ||
|
|
245ceb2d49 | ||
|
|
4c65975907 | ||
|
|
dfef7036ce | ||
|
|
44594ba726 | ||
|
|
1876c4d9df | ||
|
|
a2ff66b5d0 | ||
|
|
e3972dc5af | ||
|
|
18c0f197b2 | ||
|
|
5b371c220c | ||
|
|
78c193f0a2 | ||
|
|
274295bc97 | ||
|
|
6c7ef622c1 | ||
|
|
da1cac0d53 | ||
|
|
a84df14137 | ||
|
|
4a49f9d004 | ||
|
|
1eb4b5379a | ||
|
|
35c7fc06d7 | ||
|
|
b69d453a68 | ||
|
|
2f6fb717c1 | ||
|
|
b7e1989d45 | ||
|
|
202b03b32b | ||
|
|
1aa871ec94 | ||
|
|
4ffbb0bbd9 | ||
|
|
f859fe6517 | ||
|
|
021b425b8b | ||
|
|
d95122ca01 | ||
|
|
81d3c7351b | ||
|
|
ccb8ffd6eb | ||
|
|
5a8ea57a1b | ||
|
|
60228ec6e6 | ||
|
|
574703e551 | ||
|
|
fa154f1a8f | ||
|
|
635545630b | ||
|
|
df8afda999 | ||
|
|
f80b090c93 | ||
|
|
806173f7e3 | ||
|
|
2f6c1b82a6 | ||
|
|
b8c2808abe | ||
|
|
9027e4e065 | ||
|
|
8ca5276a0e | ||
|
|
ee45a5524d | ||
|
|
70d4223a75 | ||
|
|
7ab2840381 | ||
|
|
78c951cb70 | ||
|
|
a0a3a80151 | ||
|
|
3ecffd5588 | ||
|
|
8ea66bb0e9 | ||
|
|
9359fbbad6 | ||
|
|
1949be90c2 | ||
|
|
30970acfaf | ||
|
|
6d12a8bfa1 | ||
|
|
2fb41c8d65 | ||
|
|
835b2609b6 | ||
|
|
10ae53f108 | ||
|
|
68bfceb727 | ||
|
|
f348c7168f | ||
|
|
627d9bf45d | ||
|
|
2aee8ab511 | ||
|
|
92be8df95d | ||
|
|
b1acbf3114 | ||
|
|
8043e09ec1 | ||
|
|
25c746bb14 | ||
|
|
a91e8b26f6 | ||
|
|
e826ea5d04 | ||
|
|
23a9780ebb | ||
|
|
9cb8ebbaa7 | ||
|
|
ded520c2c1 | ||
|
|
a77157391c | ||
|
|
03892bad5e | ||
|
|
77fef02116 | ||
|
|
f3328c41fb | ||
|
|
23ae259c82 | ||
|
|
45f25ca62d |
3
.github/DISCUSSION_TEMPLATE/2-4.yml
vendored
3
.github/DISCUSSION_TEMPLATE/2-4.yml
vendored
@@ -32,6 +32,9 @@ body:
|
|||||||
- 2.4.170
|
- 2.4.170
|
||||||
- 2.4.180
|
- 2.4.180
|
||||||
- 2.4.190
|
- 2.4.190
|
||||||
|
- 2.4.200
|
||||||
|
- 2.4.201
|
||||||
|
- 2.4.210
|
||||||
- Other (please provide detail below)
|
- Other (please provide detail below)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
2
.github/workflows/pythontest.yml
vendored
2
.github/workflows/pythontest.yml
vendored
@@ -4,7 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- "salt/sensoroni/files/analyzers/**"
|
- "salt/sensoroni/files/analyzers/**"
|
||||||
- "salt/manager/tools/sbin"
|
- "salt/manager/tools/sbin/**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
### 2.4.190-20251024 ISO image released on 2025/10/24
|
### 2.4.201-20260114 ISO image released on 2026/1/15
|
||||||
|
|
||||||
|
|
||||||
### Download and Verify
|
### Download and Verify
|
||||||
|
|
||||||
2.4.190-20251024 ISO image:
|
2.4.201-20260114 ISO image:
|
||||||
https://download.securityonion.net/file/securityonion/securityonion-2.4.190-20251024.iso
|
https://download.securityonion.net/file/securityonion/securityonion-2.4.201-20260114.iso
|
||||||
|
|
||||||
MD5: 25358481FB876226499C011FC0710358
|
MD5: 20E926E433203798512EF46E590C89B9
|
||||||
SHA1: 0B26173C0CE136F2CA40A15046D1DFB78BCA1165
|
SHA1: 779E4084A3E1A209B494493B8F5658508B6014FA
|
||||||
SHA256: 4FD9F62EDA672408828B3C0C446FE5EA9FF3C4EE8488A7AB1101544A3C487872
|
SHA256: 3D10E7C885AEC5C5D4F4E50F9644FF9728E8C0A2E36EBB8C96B32569685A7C40
|
||||||
|
|
||||||
Signature for ISO image:
|
Signature for ISO image:
|
||||||
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.190-20251024.iso.sig
|
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.201-20260114.iso.sig
|
||||||
|
|
||||||
Signing key:
|
Signing key:
|
||||||
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS
|
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:
|
Download the signature file for the ISO:
|
||||||
```
|
```
|
||||||
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.190-20251024.iso.sig
|
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.201-20260114.iso.sig
|
||||||
```
|
```
|
||||||
|
|
||||||
Download the ISO image:
|
Download the ISO image:
|
||||||
```
|
```
|
||||||
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.190-20251024.iso
|
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.201-20260114.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
Verify the downloaded ISO image using the signature file:
|
Verify the downloaded ISO image using the signature file:
|
||||||
```
|
```
|
||||||
gpg --verify securityonion-2.4.190-20251024.iso.sig securityonion-2.4.190-20251024.iso
|
gpg --verify securityonion-2.4.201-20260114.iso.sig securityonion-2.4.201-20260114.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
|
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
|
||||||
```
|
```
|
||||||
gpg: Signature made Thu 23 Oct 2025 07:21:46 AM EDT using RSA key ID FE507013
|
gpg: Signature made Wed 14 Jan 2026 05:23:39 PM EST using RSA key ID FE507013
|
||||||
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
|
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
|
||||||
gpg: WARNING: This key is not certified with a trusted signature!
|
gpg: WARNING: This key is not certified with a trusted signature!
|
||||||
gpg: There is no indication that the signature belongs to the owner.
|
gpg: There is no indication that the signature belongs to the owner.
|
||||||
|
|||||||
2
pillar/ca/init.sls
Normal file
2
pillar/ca/init.sls
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ca:
|
||||||
|
server:
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
base:
|
base:
|
||||||
'*':
|
'*':
|
||||||
|
- ca
|
||||||
- global.soc_global
|
- global.soc_global
|
||||||
- global.adv_global
|
- global.adv_global
|
||||||
- docker.soc_docker
|
- docker.soc_docker
|
||||||
@@ -43,8 +44,6 @@ base:
|
|||||||
- secrets
|
- secrets
|
||||||
- manager.soc_manager
|
- manager.soc_manager
|
||||||
- manager.adv_manager
|
- manager.adv_manager
|
||||||
- idstools.soc_idstools
|
|
||||||
- idstools.adv_idstools
|
|
||||||
- logstash.nodes
|
- logstash.nodes
|
||||||
- logstash.soc_logstash
|
- logstash.soc_logstash
|
||||||
- logstash.adv_logstash
|
- logstash.adv_logstash
|
||||||
@@ -117,8 +116,6 @@ base:
|
|||||||
- elastalert.adv_elastalert
|
- elastalert.adv_elastalert
|
||||||
- manager.soc_manager
|
- manager.soc_manager
|
||||||
- manager.adv_manager
|
- manager.adv_manager
|
||||||
- idstools.soc_idstools
|
|
||||||
- idstools.adv_idstools
|
|
||||||
- soc.soc_soc
|
- soc.soc_soc
|
||||||
- soc.adv_soc
|
- soc.adv_soc
|
||||||
- kibana.soc_kibana
|
- kibana.soc_kibana
|
||||||
@@ -158,8 +155,6 @@ base:
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
- secrets
|
- secrets
|
||||||
- healthcheck.standalone
|
- healthcheck.standalone
|
||||||
- idstools.soc_idstools
|
|
||||||
- idstools.adv_idstools
|
|
||||||
- kratos.soc_kratos
|
- kratos.soc_kratos
|
||||||
- kratos.adv_kratos
|
- kratos.adv_kratos
|
||||||
- hydra.soc_hydra
|
- hydra.soc_hydra
|
||||||
|
|||||||
@@ -172,7 +172,15 @@ MANAGER_HOSTNAME = socket.gethostname()
|
|||||||
|
|
||||||
def _download_image():
|
def _download_image():
|
||||||
"""
|
"""
|
||||||
Download and validate the Oracle Linux KVM image.
|
Download and validate the Oracle Linux KVM image with retry logic and progress monitoring.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Detects stalled downloads (no progress for 30 seconds)
|
||||||
|
- Retries up to 3 times on failure
|
||||||
|
- Connection timeout of 30 seconds
|
||||||
|
- Read timeout of 60 seconds
|
||||||
|
- Cleans up partial downloads on failure
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if successful or file exists with valid checksum, False on error
|
bool: True if successful or file exists with valid checksum, False on error
|
||||||
"""
|
"""
|
||||||
@@ -185,45 +193,107 @@ def _download_image():
|
|||||||
os.unlink(IMAGE_PATH)
|
os.unlink(IMAGE_PATH)
|
||||||
|
|
||||||
log.info("Starting image download process")
|
log.info("Starting image download process")
|
||||||
|
|
||||||
|
# Retry configuration
|
||||||
|
max_attempts = 3
|
||||||
|
retry_delay = 5 # seconds to wait between retry attempts
|
||||||
|
stall_timeout = 30 # seconds without progress before considering download stalled
|
||||||
|
connection_timeout = 30 # seconds to establish connection
|
||||||
|
read_timeout = 60 # seconds to wait for data chunks
|
||||||
|
|
||||||
|
for attempt in range(1, max_attempts + 1):
|
||||||
|
log.info("Download attempt %d of %d", attempt, max_attempts)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Download file with timeouts
|
||||||
|
log.info("Downloading Oracle Linux KVM image from %s to %s", IMAGE_URL, IMAGE_PATH)
|
||||||
|
response = requests.get(
|
||||||
|
IMAGE_URL,
|
||||||
|
stream=True,
|
||||||
|
timeout=(connection_timeout, read_timeout)
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
try:
|
# Get total file size for progress tracking
|
||||||
# Download file
|
total_size = int(response.headers.get('content-length', 0))
|
||||||
log.info("Downloading Oracle Linux KVM image from %s to %s", IMAGE_URL, IMAGE_PATH)
|
downloaded_size = 0
|
||||||
response = requests.get(IMAGE_URL, stream=True)
|
last_log_time = 0
|
||||||
response.raise_for_status()
|
last_progress_time = time.time()
|
||||||
|
last_downloaded_size = 0
|
||||||
|
|
||||||
# Get total file size for progress tracking
|
# Save file with progress logging and stall detection
|
||||||
total_size = int(response.headers.get('content-length', 0))
|
with salt.utils.files.fopen(IMAGE_PATH, 'wb') as f:
|
||||||
downloaded_size = 0
|
for chunk in response.iter_content(chunk_size=8192):
|
||||||
last_log_time = 0
|
if chunk: # filter out keep-alive new chunks
|
||||||
|
f.write(chunk)
|
||||||
|
downloaded_size += len(chunk)
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
# Check for stalled download
|
||||||
|
if downloaded_size > last_downloaded_size:
|
||||||
|
# Progress made, reset stall timer
|
||||||
|
last_progress_time = current_time
|
||||||
|
last_downloaded_size = downloaded_size
|
||||||
|
elif current_time - last_progress_time > stall_timeout:
|
||||||
|
# No progress for stall_timeout seconds
|
||||||
|
raise Exception(
|
||||||
|
f"Download stalled: no progress for {stall_timeout} seconds "
|
||||||
|
f"at {downloaded_size}/{total_size} bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Log progress every second
|
||||||
|
if current_time - last_log_time >= 1:
|
||||||
|
progress = (downloaded_size / total_size) * 100 if total_size > 0 else 0
|
||||||
|
log.info("Progress - %.1f%% (%d/%d bytes)",
|
||||||
|
progress, downloaded_size, total_size)
|
||||||
|
last_log_time = current_time
|
||||||
|
|
||||||
# Save file with progress logging
|
# Validate downloaded file
|
||||||
with salt.utils.files.fopen(IMAGE_PATH, 'wb') as f:
|
log.info("Download complete, validating checksum...")
|
||||||
for chunk in response.iter_content(chunk_size=8192):
|
if not _validate_image_checksum(IMAGE_PATH, IMAGE_SHA256):
|
||||||
f.write(chunk)
|
log.error("Checksum validation failed on attempt %d", attempt)
|
||||||
downloaded_size += len(chunk)
|
os.unlink(IMAGE_PATH)
|
||||||
|
if attempt < max_attempts:
|
||||||
|
log.info("Will retry download...")
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
log.error("All download attempts failed due to checksum mismatch")
|
||||||
|
return False
|
||||||
|
|
||||||
|
log.info("Successfully downloaded and validated Oracle Linux KVM image")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except requests.exceptions.Timeout as e:
|
||||||
|
log.error("Download attempt %d failed: Timeout - %s", attempt, str(e))
|
||||||
|
if os.path.exists(IMAGE_PATH):
|
||||||
|
os.unlink(IMAGE_PATH)
|
||||||
|
if attempt < max_attempts:
|
||||||
|
log.info("Will retry download in %d seconds...", retry_delay)
|
||||||
|
time.sleep(retry_delay)
|
||||||
|
else:
|
||||||
|
log.error("All download attempts failed due to timeout")
|
||||||
|
|
||||||
# Log progress every second
|
except requests.exceptions.RequestException as e:
|
||||||
current_time = time.time()
|
log.error("Download attempt %d failed: Network error - %s", attempt, str(e))
|
||||||
if current_time - last_log_time >= 1:
|
if os.path.exists(IMAGE_PATH):
|
||||||
progress = (downloaded_size / total_size) * 100 if total_size > 0 else 0
|
os.unlink(IMAGE_PATH)
|
||||||
log.info("Progress - %.1f%% (%d/%d bytes)",
|
if attempt < max_attempts:
|
||||||
progress, downloaded_size, total_size)
|
log.info("Will retry download in %d seconds...", retry_delay)
|
||||||
last_log_time = current_time
|
time.sleep(retry_delay)
|
||||||
|
else:
|
||||||
# Validate downloaded file
|
log.error("All download attempts failed due to network errors")
|
||||||
if not _validate_image_checksum(IMAGE_PATH, IMAGE_SHA256):
|
|
||||||
os.unlink(IMAGE_PATH)
|
except Exception as e:
|
||||||
return False
|
log.error("Download attempt %d failed: %s", attempt, str(e))
|
||||||
|
if os.path.exists(IMAGE_PATH):
|
||||||
log.info("Successfully downloaded and validated Oracle Linux KVM image")
|
os.unlink(IMAGE_PATH)
|
||||||
return True
|
if attempt < max_attempts:
|
||||||
|
log.info("Will retry download in %d seconds...", retry_delay)
|
||||||
except Exception as e:
|
time.sleep(retry_delay)
|
||||||
log.error("Error downloading hypervisor image: %s", str(e))
|
else:
|
||||||
if os.path.exists(IMAGE_PATH):
|
log.error("All download attempts failed")
|
||||||
os.unlink(IMAGE_PATH)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _check_ssh_keys_exist():
|
def _check_ssh_keys_exist():
|
||||||
"""
|
"""
|
||||||
@@ -419,25 +489,28 @@ def _ensure_hypervisor_host_dir(minion_id: str = None):
|
|||||||
log.error(f"Error creating hypervisor host directory: {str(e)}")
|
log.error(f"Error creating hypervisor host directory: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _apply_dyanno_hypervisor_state():
|
def _apply_dyanno_hypervisor_state(status):
|
||||||
"""
|
"""
|
||||||
Apply the soc.dyanno.hypervisor state on the salt master.
|
Apply the soc.dyanno.hypervisor state on the salt master.
|
||||||
|
|
||||||
This function applies the soc.dyanno.hypervisor state on the salt master
|
This function applies the soc.dyanno.hypervisor state on the salt master
|
||||||
to update the hypervisor annotation and ensure all hypervisor host directories exist.
|
to update the hypervisor annotation and ensure all hypervisor host directories exist.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
status: Status passed to the hypervisor annotation state
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if state was applied successfully, False otherwise
|
bool: True if state was applied successfully, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
log.info("Applying soc.dyanno.hypervisor state on salt master")
|
log.info(f"Applying soc.dyanno.hypervisor state on salt master with status: {status}")
|
||||||
|
|
||||||
# Initialize the LocalClient
|
# Initialize the LocalClient
|
||||||
local = salt.client.LocalClient()
|
local = salt.client.LocalClient()
|
||||||
|
|
||||||
# Target the salt master to apply the soc.dyanno.hypervisor state
|
# Target the salt master to apply the soc.dyanno.hypervisor state
|
||||||
target = MANAGER_HOSTNAME + '_*'
|
target = MANAGER_HOSTNAME + '_*'
|
||||||
state_result = local.cmd(target, 'state.apply', ['soc.dyanno.hypervisor', "pillar={'baseDomain': {'status': 'PreInit'}}", 'concurrent=True'], tgt_type='glob')
|
state_result = local.cmd(target, 'state.apply', ['soc.dyanno.hypervisor', f"pillar={{'baseDomain': {{'status': '{status}'}}}}", 'concurrent=True'], tgt_type='glob')
|
||||||
log.debug(f"state_result: {state_result}")
|
log.debug(f"state_result: {state_result}")
|
||||||
# Check if state was applied successfully
|
# Check if state was applied successfully
|
||||||
if state_result:
|
if state_result:
|
||||||
@@ -454,17 +527,17 @@ def _apply_dyanno_hypervisor_state():
|
|||||||
success = False
|
success = False
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
log.info("Successfully applied soc.dyanno.hypervisor state")
|
log.info(f"Successfully applied soc.dyanno.hypervisor state with status: {status}")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
log.error("Failed to apply soc.dyanno.hypervisor state")
|
log.error(f"Failed to apply soc.dyanno.hypervisor state with status: {status}")
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
log.error("No response from salt master when applying soc.dyanno.hypervisor state")
|
log.error(f"No response from salt master when applying soc.dyanno.hypervisor state with status: {status}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"Error applying soc.dyanno.hypervisor state: {str(e)}")
|
log.error(f"Error applying soc.dyanno.hypervisor state with status: {status}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _apply_cloud_config_state():
|
def _apply_cloud_config_state():
|
||||||
@@ -598,11 +671,6 @@ def setup_environment(vm_name: str = 'sool9', disk_size: str = '220G', minion_id
|
|||||||
log.warning("Failed to apply salt.cloud.config state, continuing with setup")
|
log.warning("Failed to apply salt.cloud.config state, continuing with setup")
|
||||||
# We don't return an error here as we want to continue with the setup process
|
# We don't return an error here as we want to continue with the setup process
|
||||||
|
|
||||||
# Apply the soc.dyanno.hypervisor state on the salt master
|
|
||||||
if not _apply_dyanno_hypervisor_state():
|
|
||||||
log.warning("Failed to apply soc.dyanno.hypervisor state, continuing with setup")
|
|
||||||
# We don't return an error here as we want to continue with the setup process
|
|
||||||
|
|
||||||
log.info("Starting setup_environment in setup_hypervisor runner")
|
log.info("Starting setup_environment in setup_hypervisor runner")
|
||||||
|
|
||||||
# Check if environment is already set up
|
# Check if environment is already set up
|
||||||
@@ -616,9 +684,12 @@ def setup_environment(vm_name: str = 'sool9', disk_size: str = '220G', minion_id
|
|||||||
|
|
||||||
# Handle image setup if needed
|
# Handle image setup if needed
|
||||||
if not image_valid:
|
if not image_valid:
|
||||||
|
_apply_dyanno_hypervisor_state('ImageDownloadStart')
|
||||||
log.info("Starting image download/validation process")
|
log.info("Starting image download/validation process")
|
||||||
if not _download_image():
|
if not _download_image():
|
||||||
log.error("Image download failed")
|
log.error("Image download failed")
|
||||||
|
# Update hypervisor annotation with failure status
|
||||||
|
_apply_dyanno_hypervisor_state('ImageDownloadFailed')
|
||||||
return {
|
return {
|
||||||
'success': False,
|
'success': False,
|
||||||
'error': 'Image download failed',
|
'error': 'Image download failed',
|
||||||
@@ -631,6 +702,8 @@ def setup_environment(vm_name: str = 'sool9', disk_size: str = '220G', minion_id
|
|||||||
log.info("Setting up SSH keys")
|
log.info("Setting up SSH keys")
|
||||||
if not _setup_ssh_keys():
|
if not _setup_ssh_keys():
|
||||||
log.error("SSH key setup failed")
|
log.error("SSH key setup failed")
|
||||||
|
# Update hypervisor annotation with failure status
|
||||||
|
_apply_dyanno_hypervisor_state('SSHKeySetupFailed')
|
||||||
return {
|
return {
|
||||||
'success': False,
|
'success': False,
|
||||||
'error': 'SSH key setup failed',
|
'error': 'SSH key setup failed',
|
||||||
@@ -655,6 +728,12 @@ def setup_environment(vm_name: str = 'sool9', disk_size: str = '220G', minion_id
|
|||||||
success = vm_result.get('success', False)
|
success = vm_result.get('success', False)
|
||||||
log.info("Setup environment completed with status: %s", "SUCCESS" if success else "FAILED")
|
log.info("Setup environment completed with status: %s", "SUCCESS" if success else "FAILED")
|
||||||
|
|
||||||
|
# Update hypervisor annotation with success status
|
||||||
|
if success:
|
||||||
|
_apply_dyanno_hypervisor_state('PreInit')
|
||||||
|
else:
|
||||||
|
_apply_dyanno_hypervisor_state('SetupFailed')
|
||||||
|
|
||||||
# If setup was successful and we have a minion_id, run highstate
|
# If setup was successful and we have a minion_id, run highstate
|
||||||
if success and minion_id:
|
if success and minion_id:
|
||||||
log.info("Running highstate on hypervisor %s", minion_id)
|
log.info("Running highstate on hypervisor %s", minion_id)
|
||||||
|
|||||||
@@ -15,11 +15,7 @@
|
|||||||
'salt.minion-check',
|
'salt.minion-check',
|
||||||
'sensoroni',
|
'sensoroni',
|
||||||
'salt.lasthighstate',
|
'salt.lasthighstate',
|
||||||
'salt.minion'
|
'salt.minion',
|
||||||
] %}
|
|
||||||
|
|
||||||
{% set ssl_states = [
|
|
||||||
'ssl',
|
|
||||||
'telegraf',
|
'telegraf',
|
||||||
'firewall',
|
'firewall',
|
||||||
'schedule',
|
'schedule',
|
||||||
@@ -28,7 +24,7 @@
|
|||||||
|
|
||||||
{% set manager_states = [
|
{% set manager_states = [
|
||||||
'salt.master',
|
'salt.master',
|
||||||
'ca',
|
'ca.server',
|
||||||
'registry',
|
'registry',
|
||||||
'manager',
|
'manager',
|
||||||
'nginx',
|
'nginx',
|
||||||
@@ -38,8 +34,6 @@
|
|||||||
'hydra',
|
'hydra',
|
||||||
'elasticfleet',
|
'elasticfleet',
|
||||||
'elastic-fleet-package-registry',
|
'elastic-fleet-package-registry',
|
||||||
'idstools',
|
|
||||||
'suricata.manager',
|
|
||||||
'utility'
|
'utility'
|
||||||
] %}
|
] %}
|
||||||
|
|
||||||
@@ -77,28 +71,24 @@
|
|||||||
{# Map role-specific states #}
|
{# Map role-specific states #}
|
||||||
{% set role_states = {
|
{% set role_states = {
|
||||||
'so-eval': (
|
'so-eval': (
|
||||||
ssl_states +
|
|
||||||
manager_states +
|
manager_states +
|
||||||
sensor_states +
|
sensor_states +
|
||||||
elastic_stack_states | reject('equalto', 'logstash') | list
|
elastic_stack_states | reject('equalto', 'logstash') | list +
|
||||||
|
['logstash.ssl']
|
||||||
),
|
),
|
||||||
'so-heavynode': (
|
'so-heavynode': (
|
||||||
ssl_states +
|
|
||||||
sensor_states +
|
sensor_states +
|
||||||
['elasticagent', 'elasticsearch', 'logstash', 'redis', 'nginx']
|
['elasticagent', 'elasticsearch', 'logstash', 'redis', 'nginx']
|
||||||
),
|
),
|
||||||
'so-idh': (
|
'so-idh': (
|
||||||
ssl_states +
|
|
||||||
['idh']
|
['idh']
|
||||||
),
|
),
|
||||||
'so-import': (
|
'so-import': (
|
||||||
ssl_states +
|
|
||||||
manager_states +
|
manager_states +
|
||||||
sensor_states | reject('equalto', 'strelka') | reject('equalto', 'healthcheck') | list +
|
sensor_states | reject('equalto', 'strelka') | reject('equalto', 'healthcheck') | list +
|
||||||
['elasticsearch', 'elasticsearch.auth', 'kibana', 'kibana.secrets', 'strelka.manager']
|
['elasticsearch', 'elasticsearch.auth', 'kibana', 'kibana.secrets', 'logstash.ssl', 'strelka.manager']
|
||||||
),
|
),
|
||||||
'so-manager': (
|
'so-manager': (
|
||||||
ssl_states +
|
|
||||||
manager_states +
|
manager_states +
|
||||||
['salt.cloud', 'libvirt.packages', 'libvirt.ssh.users', 'strelka.manager'] +
|
['salt.cloud', 'libvirt.packages', 'libvirt.ssh.users', 'strelka.manager'] +
|
||||||
stig_states +
|
stig_states +
|
||||||
@@ -106,7 +96,6 @@
|
|||||||
elastic_stack_states
|
elastic_stack_states
|
||||||
),
|
),
|
||||||
'so-managerhype': (
|
'so-managerhype': (
|
||||||
ssl_states +
|
|
||||||
manager_states +
|
manager_states +
|
||||||
['salt.cloud', 'strelka.manager', 'hypervisor', 'libvirt'] +
|
['salt.cloud', 'strelka.manager', 'hypervisor', 'libvirt'] +
|
||||||
stig_states +
|
stig_states +
|
||||||
@@ -114,7 +103,6 @@
|
|||||||
elastic_stack_states
|
elastic_stack_states
|
||||||
),
|
),
|
||||||
'so-managersearch': (
|
'so-managersearch': (
|
||||||
ssl_states +
|
|
||||||
manager_states +
|
manager_states +
|
||||||
['salt.cloud', 'libvirt.packages', 'libvirt.ssh.users', 'strelka.manager'] +
|
['salt.cloud', 'libvirt.packages', 'libvirt.ssh.users', 'strelka.manager'] +
|
||||||
stig_states +
|
stig_states +
|
||||||
@@ -122,12 +110,10 @@
|
|||||||
elastic_stack_states
|
elastic_stack_states
|
||||||
),
|
),
|
||||||
'so-searchnode': (
|
'so-searchnode': (
|
||||||
ssl_states +
|
|
||||||
['kafka.ca', 'kafka.ssl', 'elasticsearch', 'logstash', 'nginx'] +
|
['kafka.ca', 'kafka.ssl', 'elasticsearch', 'logstash', 'nginx'] +
|
||||||
stig_states
|
stig_states
|
||||||
),
|
),
|
||||||
'so-standalone': (
|
'so-standalone': (
|
||||||
ssl_states +
|
|
||||||
manager_states +
|
manager_states +
|
||||||
['salt.cloud', 'libvirt.packages', 'libvirt.ssh.users'] +
|
['salt.cloud', 'libvirt.packages', 'libvirt.ssh.users'] +
|
||||||
sensor_states +
|
sensor_states +
|
||||||
@@ -136,29 +122,24 @@
|
|||||||
elastic_stack_states
|
elastic_stack_states
|
||||||
),
|
),
|
||||||
'so-sensor': (
|
'so-sensor': (
|
||||||
ssl_states +
|
|
||||||
sensor_states +
|
sensor_states +
|
||||||
['nginx'] +
|
['nginx'] +
|
||||||
stig_states
|
stig_states
|
||||||
),
|
),
|
||||||
'so-fleet': (
|
'so-fleet': (
|
||||||
ssl_states +
|
|
||||||
stig_states +
|
stig_states +
|
||||||
['logstash', 'nginx', 'healthcheck', 'elasticfleet']
|
['logstash', 'nginx', 'healthcheck', 'elasticfleet']
|
||||||
),
|
),
|
||||||
'so-receiver': (
|
'so-receiver': (
|
||||||
ssl_states +
|
|
||||||
kafka_states +
|
kafka_states +
|
||||||
stig_states +
|
stig_states +
|
||||||
['logstash', 'redis']
|
['logstash', 'redis']
|
||||||
),
|
),
|
||||||
'so-hypervisor': (
|
'so-hypervisor': (
|
||||||
ssl_states +
|
|
||||||
stig_states +
|
stig_states +
|
||||||
['hypervisor', 'libvirt']
|
['hypervisor', 'libvirt']
|
||||||
),
|
),
|
||||||
'so-desktop': (
|
'so-desktop': (
|
||||||
['ssl', 'docker_clean', 'telegraf'] +
|
|
||||||
stig_states
|
stig_states
|
||||||
)
|
)
|
||||||
} %}
|
} %}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
|
{% set PCAP_BPF_STATUS = 0 %}
|
||||||
|
{% set STENO_BPF_COMPILED = "" %}
|
||||||
|
|
||||||
{% if GLOBALS.pcap_engine == "TRANSITION" %}
|
{% if GLOBALS.pcap_engine == "TRANSITION" %}
|
||||||
{% set PCAPBPF = ["ip and host 255.255.255.1 and port 1"] %}
|
{% set PCAPBPF = ["ip and host 255.255.255.1 and port 1"] %}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -8,3 +11,11 @@
|
|||||||
{{ MACROS.remove_comments(BPFMERGED, 'pcap') }}
|
{{ MACROS.remove_comments(BPFMERGED, 'pcap') }}
|
||||||
{% set PCAPBPF = BPFMERGED.pcap %}
|
{% set PCAPBPF = BPFMERGED.pcap %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if PCAPBPF %}
|
||||||
|
{% set PCAP_BPF_CALC = salt['cmd.run_all']('/usr/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 %}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
bpf:
|
bpf:
|
||||||
pcap:
|
pcap:
|
||||||
description: List of BPF filters to apply to Stenographer.
|
description: List of BPF filters to apply to the PCAP engine.
|
||||||
multiline: True
|
multiline: True
|
||||||
forcedType: "[]string"
|
forcedType: "[]string"
|
||||||
helpLink: bpf.html
|
helpLink: bpf.html
|
||||||
suricata:
|
suricata:
|
||||||
description: List of BPF filters to apply to Suricata.
|
description: List of BPF filters to apply to Suricata. This will apply to alerts and, if enabled, to metadata and PCAP logs generated by Suricata.
|
||||||
multiline: True
|
multiline: True
|
||||||
forcedType: "[]string"
|
forcedType: "[]string"
|
||||||
helpLink: bpf.html
|
helpLink: bpf.html
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
{% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %}
|
{% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %}
|
||||||
{% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %}
|
{% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %}
|
||||||
|
{% set SURICATA_BPF_STATUS = 0 %}
|
||||||
{% import 'bpf/macros.jinja' as MACROS %}
|
{% import 'bpf/macros.jinja' as MACROS %}
|
||||||
|
|
||||||
{{ MACROS.remove_comments(BPFMERGED, 'suricata') }}
|
{{ MACROS.remove_comments(BPFMERGED, 'suricata') }}
|
||||||
|
|
||||||
{% set SURICATABPF = BPFMERGED.suricata %}
|
{% set SURICATABPF = BPFMERGED.suricata %}
|
||||||
|
|
||||||
|
{% if SURICATABPF %}
|
||||||
|
{% set SURICATA_BPF_CALC = salt['cmd.run_all']('/usr/sbin/so-bpf-compile ' ~ GLOBALS.sensor.interface ~ ' ' ~ SURICATABPF|join(" "), cwd='/root') %}
|
||||||
|
{% if SURICATA_BPF_CALC['retcode'] == 0 %}
|
||||||
|
{% set SURICATA_BPF_STATUS = 1 %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
{% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %}
|
{% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %}
|
||||||
{% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %}
|
{% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %}
|
||||||
|
{% set ZEEK_BPF_STATUS = 0 %}
|
||||||
{% import 'bpf/macros.jinja' as MACROS %}
|
{% import 'bpf/macros.jinja' as MACROS %}
|
||||||
|
|
||||||
{{ MACROS.remove_comments(BPFMERGED, 'zeek') }}
|
{{ MACROS.remove_comments(BPFMERGED, 'zeek') }}
|
||||||
|
|
||||||
{% set ZEEKBPF = BPFMERGED.zeek %}
|
{% set ZEEKBPF = BPFMERGED.zeek %}
|
||||||
|
|
||||||
|
{% if ZEEKBPF %}
|
||||||
|
{% set ZEEK_BPF_CALC = salt['cmd.run_all']('/usr/sbin/so-bpf-compile ' ~ GLOBALS.sensor.interface ~ ' ' ~ ZEEKBPF|join(" "), cwd='/root') %}
|
||||||
|
{% if ZEEK_BPF_CALC['retcode'] == 0 %}
|
||||||
|
{% set ZEEK_BPF_STATUS = 1 %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
pki_issued_certs:
|
|
||||||
file.directory:
|
|
||||||
- name: /etc/pki/issued_certs
|
|
||||||
- makedirs: True
|
|
||||||
@@ -3,70 +3,10 @@
|
|||||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# Elastic License 2.0.
|
# Elastic License 2.0.
|
||||||
|
|
||||||
{% from 'allowed_states.map.jinja' import allowed_states %}
|
|
||||||
{% if sls in allowed_states %}
|
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
|
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- ca.dirs
|
{% if GLOBALS.is_manager %}
|
||||||
|
- ca.server
|
||||||
/etc/salt/minion.d/signing_policies.conf:
|
|
||||||
file.managed:
|
|
||||||
- source: salt://ca/files/signing_policies.conf
|
|
||||||
|
|
||||||
pki_private_key:
|
|
||||||
x509.private_key_managed:
|
|
||||||
- name: /etc/pki/ca.key
|
|
||||||
- keysize: 4096
|
|
||||||
- passphrase:
|
|
||||||
- backup: True
|
|
||||||
{% if salt['file.file_exists']('/etc/pki/ca.key') -%}
|
|
||||||
- prereq:
|
|
||||||
- x509: /etc/pki/ca.crt
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
pki_public_ca_crt:
|
|
||||||
x509.certificate_managed:
|
|
||||||
- name: /etc/pki/ca.crt
|
|
||||||
- signing_private_key: /etc/pki/ca.key
|
|
||||||
- CN: {{ GLOBALS.manager }}
|
|
||||||
- C: US
|
|
||||||
- ST: Utah
|
|
||||||
- L: Salt Lake City
|
|
||||||
- basicConstraints: "critical CA:true"
|
|
||||||
- keyUsage: "critical cRLSign, keyCertSign"
|
|
||||||
- extendedkeyUsage: "serverAuth, clientAuth"
|
|
||||||
- subjectKeyIdentifier: hash
|
|
||||||
- authorityKeyIdentifier: keyid:always, issuer
|
|
||||||
- days_valid: 3650
|
|
||||||
- days_remaining: 0
|
|
||||||
- backup: True
|
|
||||||
- replace: False
|
|
||||||
- require:
|
|
||||||
- sls: ca.dirs
|
|
||||||
- timeout: 30
|
|
||||||
- retry:
|
|
||||||
attempts: 5
|
|
||||||
interval: 30
|
|
||||||
|
|
||||||
mine_update_ca_crt:
|
|
||||||
module.run:
|
|
||||||
- mine.update: []
|
|
||||||
- onchanges:
|
|
||||||
- x509: pki_public_ca_crt
|
|
||||||
|
|
||||||
cakeyperms:
|
|
||||||
file.managed:
|
|
||||||
- replace: False
|
|
||||||
- name: /etc/pki/ca.key
|
|
||||||
- mode: 640
|
|
||||||
- group: 939
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
{{sls}}_state_not_allowed:
|
|
||||||
test.fail_without_changes:
|
|
||||||
- name: {{sls}}_state_not_allowed
|
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
- ca.trustca
|
||||||
|
|||||||
3
salt/ca/map.jinja
Normal file
3
salt/ca/map.jinja
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{% set CA = {
|
||||||
|
'server': pillar.ca.server
|
||||||
|
}%}
|
||||||
@@ -1,7 +1,35 @@
|
|||||||
pki_private_key:
|
# 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.
|
||||||
|
|
||||||
|
{% set setup_running = salt['cmd.retcode']('pgrep -x so-setup') == 0 %}
|
||||||
|
|
||||||
|
{% if setup_running%}
|
||||||
|
|
||||||
|
include:
|
||||||
|
- ssl.remove
|
||||||
|
|
||||||
|
remove_pki_private_key:
|
||||||
file.absent:
|
file.absent:
|
||||||
- name: /etc/pki/ca.key
|
- name: /etc/pki/ca.key
|
||||||
|
|
||||||
pki_public_ca_crt:
|
remove_pki_public_ca_crt:
|
||||||
file.absent:
|
file.absent:
|
||||||
- name: /etc/pki/ca.crt
|
- name: /etc/pki/ca.crt
|
||||||
|
|
||||||
|
remove_trusttheca:
|
||||||
|
file.absent:
|
||||||
|
- name: /etc/pki/tls/certs/intca.crt
|
||||||
|
|
||||||
|
remove_pki_public_ca_crt_symlink:
|
||||||
|
file.absent:
|
||||||
|
- name: /opt/so/saltstack/local/salt/ca/files/ca.crt
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
so-setup_not_running:
|
||||||
|
test.show_notification:
|
||||||
|
- text: "This state is reserved for usage during so-setup."
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|||||||
63
salt/ca/server.sls
Normal file
63
salt/ca/server.sls
Normal 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 in allowed_states %}
|
||||||
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
|
|
||||||
|
pki_private_key:
|
||||||
|
x509.private_key_managed:
|
||||||
|
- name: /etc/pki/ca.key
|
||||||
|
- keysize: 4096
|
||||||
|
- passphrase:
|
||||||
|
- backup: True
|
||||||
|
{% if salt['file.file_exists']('/etc/pki/ca.key') -%}
|
||||||
|
- prereq:
|
||||||
|
- x509: /etc/pki/ca.crt
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
pki_public_ca_crt:
|
||||||
|
x509.certificate_managed:
|
||||||
|
- name: /etc/pki/ca.crt
|
||||||
|
- signing_private_key: /etc/pki/ca.key
|
||||||
|
- CN: {{ GLOBALS.manager }}
|
||||||
|
- C: US
|
||||||
|
- ST: Utah
|
||||||
|
- L: Salt Lake City
|
||||||
|
- basicConstraints: "critical CA:true"
|
||||||
|
- keyUsage: "critical cRLSign, keyCertSign"
|
||||||
|
- extendedkeyUsage: "serverAuth, clientAuth"
|
||||||
|
- subjectKeyIdentifier: hash
|
||||||
|
- authorityKeyIdentifier: keyid:always, issuer
|
||||||
|
- days_valid: 3650
|
||||||
|
- days_remaining: 7
|
||||||
|
- backup: True
|
||||||
|
- replace: False
|
||||||
|
- timeout: 30
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
pki_public_ca_crt_symlink:
|
||||||
|
file.symlink:
|
||||||
|
- name: /opt/so/saltstack/local/salt/ca/files/ca.crt
|
||||||
|
- target: /etc/pki/ca.crt
|
||||||
|
- require:
|
||||||
|
- x509: pki_public_ca_crt
|
||||||
|
|
||||||
|
cakeyperms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/ca.key
|
||||||
|
- mode: 640
|
||||||
|
- group: 939
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{{sls}}_state_not_allowed:
|
||||||
|
test.fail_without_changes:
|
||||||
|
- name: {{sls}}_state_not_allowed
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
15
salt/idstools/tools/sbin/so-idstools-start → salt/ca/signing_policy.sls
Executable file → Normal file
15
salt/idstools/tools/sbin/so-idstools-start → salt/ca/signing_policy.sls
Executable file → Normal file
@@ -1,12 +1,15 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
||||||
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
||||||
# https://securityonion.net/license; you may not use this file except in compliance with the
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
||||||
# Elastic License 2.0.
|
# Elastic License 2.0.
|
||||||
|
|
||||||
|
# when the salt-minion signs the cert, a copy is stored here
|
||||||
|
issued_certs_copypath:
|
||||||
|
file.directory:
|
||||||
|
- name: /etc/pki/issued_certs
|
||||||
|
- makedirs: True
|
||||||
|
|
||||||
|
signing_policy:
|
||||||
. /usr/sbin/so-common
|
file.managed:
|
||||||
|
- name: /etc/salt/minion.d/signing_policies.conf
|
||||||
/usr/sbin/so-start idstools $1
|
- source: salt://ca/files/signing_policies.conf
|
||||||
26
salt/ca/trustca.sls
Normal file
26
salt/ca/trustca.sls
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# 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 %}
|
||||||
|
|
||||||
|
include:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
# Trust the CA
|
||||||
|
trusttheca:
|
||||||
|
file.managed:
|
||||||
|
- name: /etc/pki/tls/certs/intca.crt
|
||||||
|
- source: salt://ca/files/ca.crt
|
||||||
|
- watch_in:
|
||||||
|
- service: docker_running
|
||||||
|
- show_changes: False
|
||||||
|
- makedirs: True
|
||||||
|
|
||||||
|
{% if GLOBALS.os_family == 'Debian' %}
|
||||||
|
symlinkca:
|
||||||
|
file.symlink:
|
||||||
|
- target: /etc/pki/tls/certs/intca.crt
|
||||||
|
- name: /etc/ssl/certs/intca.crt
|
||||||
|
{% endif %}
|
||||||
@@ -177,7 +177,7 @@ so-status_script:
|
|||||||
- source: salt://common/tools/sbin/so-status
|
- source: salt://common/tools/sbin/so-status
|
||||||
- mode: 755
|
- mode: 755
|
||||||
|
|
||||||
{% if GLOBALS.role in GLOBALS.sensor_roles %}
|
{% if GLOBALS.is_sensor %}
|
||||||
# Add sensor cleanup
|
# Add sensor cleanup
|
||||||
so-sensor-clean:
|
so-sensor-clean:
|
||||||
cron.present:
|
cron.present:
|
||||||
|
|||||||
@@ -29,9 +29,26 @@ fi
|
|||||||
|
|
||||||
interface="$1"
|
interface="$1"
|
||||||
shift
|
shift
|
||||||
tcpdump -i $interface -ddd $@ | tail -n+2 |
|
|
||||||
while read line; do
|
# Capture tcpdump output and exit code
|
||||||
|
tcpdump_output=$(tcpdump -i "$interface" -ddd "$@" 2>&1)
|
||||||
|
tcpdump_exit=$?
|
||||||
|
|
||||||
|
if [ $tcpdump_exit -ne 0 ]; then
|
||||||
|
echo "$tcpdump_output" >&2
|
||||||
|
exit $tcpdump_exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process the output, skipping the first line
|
||||||
|
echo "$tcpdump_output" | tail -n+2 | while read -r line; do
|
||||||
cols=( $line )
|
cols=( $line )
|
||||||
printf "%04x%02x%02x%08x" ${cols[0]} ${cols[1]} ${cols[2]} ${cols[3]}
|
printf "%04x%02x%02x%08x" "${cols[0]}" "${cols[1]}" "${cols[2]}" "${cols[3]}"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Check if the pipeline succeeded
|
||||||
|
if [ "${PIPESTATUS[0]}" -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
exit 0
|
||||||
|
|||||||
@@ -220,12 +220,22 @@ compare_es_versions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy_new_files() {
|
copy_new_files() {
|
||||||
|
# Define files to exclude from deletion (relative to their respective base directories)
|
||||||
|
local EXCLUDE_FILES=(
|
||||||
|
"salt/hypervisor/soc_hypervisor.yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build rsync exclude arguments
|
||||||
|
local EXCLUDE_ARGS=()
|
||||||
|
for file in "${EXCLUDE_FILES[@]}"; do
|
||||||
|
EXCLUDE_ARGS+=(--exclude="$file")
|
||||||
|
done
|
||||||
|
|
||||||
# Copy new files over to the salt dir
|
# Copy new files over to the salt dir
|
||||||
cd $UPDATE_DIR
|
cd $UPDATE_DIR
|
||||||
rsync -a salt $DEFAULT_SALT_DIR/ --delete
|
rsync -a salt $DEFAULT_SALT_DIR/ --delete "${EXCLUDE_ARGS[@]}"
|
||||||
rsync -a pillar $DEFAULT_SALT_DIR/ --delete
|
rsync -a pillar $DEFAULT_SALT_DIR/ --delete "${EXCLUDE_ARGS[@]}"
|
||||||
chown -R socore:socore $DEFAULT_SALT_DIR/
|
chown -R socore:socore $DEFAULT_SALT_DIR/
|
||||||
chmod 755 $DEFAULT_SALT_DIR/pillar/firewall/addfirewall.sh
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +395,7 @@ is_manager_node() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is_sensor_node() {
|
is_sensor_node() {
|
||||||
# Check to see if this is a sensor (forward) node
|
# Check to see if this is a sensor node
|
||||||
is_single_node_grid && return 0
|
is_single_node_grid && return 0
|
||||||
grep "role: so-" /etc/salt/grains | grep -E "sensor|heavynode" &> /dev/null
|
grep "role: so-" /etc/salt/grains | grep -E "sensor|heavynode" &> /dev/null
|
||||||
}
|
}
|
||||||
@@ -544,21 +554,39 @@ run_check_net_err() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wait_for_salt_minion() {
|
wait_for_salt_minion() {
|
||||||
local minion="$1"
|
local minion="$1"
|
||||||
local timeout="${2:-5}"
|
local max_wait="${2:-30}"
|
||||||
local logfile="${3:-'/dev/stdout'}"
|
local interval="${3:-2}"
|
||||||
retry 60 5 "journalctl -u salt-minion.service | grep 'Minion is ready to receive requests'" >> "$logfile" 2>&1 || fail
|
local logfile="${4:-'/dev/stdout'}"
|
||||||
local attempt=0
|
local elapsed=0
|
||||||
# each attempts would take about 15 seconds
|
|
||||||
local maxAttempts=20
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - Waiting for salt-minion '$minion' to be ready..."
|
||||||
until check_salt_minion_status "$minion" "$timeout" "$logfile"; do
|
|
||||||
attempt=$((attempt+1))
|
while [ $elapsed -lt $max_wait ]; do
|
||||||
if [[ $attempt -eq $maxAttempts ]]; then
|
# Check if service is running
|
||||||
return 1
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - Check if salt-minion service is running"
|
||||||
fi
|
if ! systemctl is-active --quiet salt-minion; then
|
||||||
sleep 10
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - salt-minion service not running (elapsed: ${elapsed}s)"
|
||||||
done
|
sleep $interval
|
||||||
return 0
|
elapsed=$((elapsed + interval))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - salt-minion service is running"
|
||||||
|
|
||||||
|
# Check if minion responds to ping
|
||||||
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - Check if $minion responds to ping"
|
||||||
|
if salt "$minion" test.ping --timeout=3 --out=json 2>> "$logfile" | grep -q "true"; then
|
||||||
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - salt-minion '$minion' is connected and ready!"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - Waiting... (${elapsed}s / ${max_wait}s)"
|
||||||
|
sleep $interval
|
||||||
|
elapsed=$((elapsed + interval))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$(date '+%a %d %b %Y %H:%M:%S.%6N') - ERROR: salt-minion '$minion' not ready after $max_wait seconds"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
salt_minion_count() {
|
salt_minion_count() {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ container_list() {
|
|||||||
if [ $MANAGERCHECK == 'so-import' ]; then
|
if [ $MANAGERCHECK == 'so-import' ]; then
|
||||||
TRUSTED_CONTAINERS=(
|
TRUSTED_CONTAINERS=(
|
||||||
"so-elasticsearch"
|
"so-elasticsearch"
|
||||||
"so-idstools"
|
|
||||||
"so-influxdb"
|
"so-influxdb"
|
||||||
"so-kibana"
|
"so-kibana"
|
||||||
"so-kratos"
|
"so-kratos"
|
||||||
@@ -49,7 +48,6 @@ container_list() {
|
|||||||
"so-elastic-fleet-package-registry"
|
"so-elastic-fleet-package-registry"
|
||||||
"so-elasticsearch"
|
"so-elasticsearch"
|
||||||
"so-idh"
|
"so-idh"
|
||||||
"so-idstools"
|
|
||||||
"so-influxdb"
|
"so-influxdb"
|
||||||
"so-kafka"
|
"so-kafka"
|
||||||
"so-kibana"
|
"so-kibana"
|
||||||
@@ -62,8 +60,6 @@ container_list() {
|
|||||||
"so-soc"
|
"so-soc"
|
||||||
"so-steno"
|
"so-steno"
|
||||||
"so-strelka-backend"
|
"so-strelka-backend"
|
||||||
"so-strelka-filestream"
|
|
||||||
"so-strelka-frontend"
|
|
||||||
"so-strelka-manager"
|
"so-strelka-manager"
|
||||||
"so-suricata"
|
"so-suricata"
|
||||||
"so-telegraf"
|
"so-telegraf"
|
||||||
@@ -71,7 +67,6 @@ container_list() {
|
|||||||
)
|
)
|
||||||
else
|
else
|
||||||
TRUSTED_CONTAINERS=(
|
TRUSTED_CONTAINERS=(
|
||||||
"so-idstools"
|
|
||||||
"so-elasticsearch"
|
"so-elasticsearch"
|
||||||
"so-logstash"
|
"so-logstash"
|
||||||
"so-nginx"
|
"so-nginx"
|
||||||
|
|||||||
@@ -129,6 +129,8 @@ if [[ $EXCLUDE_STARTUP_ERRORS == 'Y' ]]; then
|
|||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|responded with status-code 503" # telegraf getting 503 from ES during startup
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|responded with status-code 503" # telegraf getting 503 from ES during startup
|
||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|process_cluster_event_timeout_exception" # logstash waiting for elasticsearch to start
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|process_cluster_event_timeout_exception" # logstash waiting for elasticsearch to start
|
||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|not configured for GeoIP" # SO does not bundle the maxminddb with Zeek
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|not configured for GeoIP" # SO does not bundle the maxminddb with Zeek
|
||||||
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|HTTP 404: Not Found" # Salt loops until Kratos returns 200, during startup Kratos may not be ready
|
||||||
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|Cancelling deferred write event maybeFenceReplicas because the event queue is now closed" # Kafka controller log during shutdown/restart
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $EXCLUDE_FALSE_POSITIVE_ERRORS == 'Y' ]]; then
|
if [[ $EXCLUDE_FALSE_POSITIVE_ERRORS == 'Y' ]]; then
|
||||||
@@ -159,7 +161,9 @@ if [[ $EXCLUDE_FALSE_POSITIVE_ERRORS == 'Y' ]]; then
|
|||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|adding ingest pipeline" # false positive (elasticsearch ingest pipeline names contain 'error')
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|adding ingest pipeline" # false positive (elasticsearch ingest pipeline names contain 'error')
|
||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|updating index template" # false positive (elasticsearch index or template names contain 'error')
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|updating index template" # false positive (elasticsearch index or template names contain 'error')
|
||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|updating component template" # false positive (elasticsearch index or template names contain 'error')
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|updating component template" # false positive (elasticsearch index or template names contain 'error')
|
||||||
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|upgrading component template" # false positive (elasticsearch index or template names contain 'error')
|
||||||
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|upgrading composable template" # false positive (elasticsearch composable template names contain 'error')
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|upgrading composable template" # false positive (elasticsearch composable template names contain 'error')
|
||||||
|
EXCLUDED_ERRORS="$EXCLUDED_ERRORS|Error while parsing document for index \[.ds-logs-kratos-so-.*object mapping for \[file\]" # false positive (mapping error occuring BEFORE kratos index has rolled over in 2.4.210)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $EXCLUDE_KNOWN_ERRORS == 'Y' ]]; then
|
if [[ $EXCLUDE_KNOWN_ERRORS == 'Y' ]]; then
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ function suricata() {
|
|||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v /opt/so/conf/suricata/suricata.yaml:/etc/suricata/suricata.yaml:ro \
|
-v /opt/so/conf/suricata/suricata.yaml:/etc/suricata/suricata.yaml:ro \
|
||||||
-v /opt/so/conf/suricata/threshold.conf:/etc/suricata/threshold.conf:ro \
|
-v /opt/so/conf/suricata/threshold.conf:/etc/suricata/threshold.conf:ro \
|
||||||
-v /opt/so/conf/suricata/rules:/etc/suricata/rules:ro \
|
-v /opt/so/rules/suricata/:/etc/suricata/rules:ro \
|
||||||
-v ${LOG_PATH}:/var/log/suricata/:rw \
|
-v ${LOG_PATH}:/var/log/suricata/:rw \
|
||||||
-v ${NSM_PATH}/:/nsm/:rw \
|
-v ${NSM_PATH}/:/nsm/:rw \
|
||||||
-v "$PCAP:/input.pcap:ro" \
|
-v "$PCAP:/input.pcap:ro" \
|
||||||
|
|||||||
@@ -3,29 +3,16 @@
|
|||||||
{# we only want this state to run it is CentOS #}
|
{# we only want this state to run it is CentOS #}
|
||||||
{% if GLOBALS.os == 'OEL' %}
|
{% if GLOBALS.os == 'OEL' %}
|
||||||
|
|
||||||
{% set global_ca_text = [] %}
|
|
||||||
{% set global_ca_server = [] %}
|
|
||||||
{% set manager = GLOBALS.manager %}
|
|
||||||
{% set x509dict = salt['mine.get'](manager | lower~'*', 'x509.get_pem_entries') %}
|
|
||||||
{% for host in x509dict %}
|
|
||||||
{% if host.split('_')|last in ['manager', 'managersearch', 'standalone', 'import', 'eval'] %}
|
|
||||||
{% do global_ca_text.append(x509dict[host].get('/etc/pki/ca.crt')|replace('\n', '')) %}
|
|
||||||
{% do global_ca_server.append(host) %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% set trusttheca_text = global_ca_text[0] %}
|
|
||||||
{% set ca_server = global_ca_server[0] %}
|
|
||||||
|
|
||||||
trusted_ca:
|
trusted_ca:
|
||||||
x509.pem_managed:
|
file.managed:
|
||||||
- name: /etc/pki/ca-trust/source/anchors/ca.crt
|
- name: /etc/pki/ca-trust/source/anchors/ca.crt
|
||||||
- text: {{ trusttheca_text }}
|
- source: salt://ca/files/ca.crt
|
||||||
|
|
||||||
update_ca_certs:
|
update_ca_certs:
|
||||||
cmd.run:
|
cmd.run:
|
||||||
- name: update-ca-trust
|
- name: update-ca-trust
|
||||||
- onchanges:
|
- onchanges:
|
||||||
- x509: trusted_ca
|
- file: trusted_ca
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,6 @@ docker:
|
|||||||
custom_bind_mounts: []
|
custom_bind_mounts: []
|
||||||
extra_hosts: []
|
extra_hosts: []
|
||||||
extra_env: []
|
extra_env: []
|
||||||
'so-idstools':
|
|
||||||
final_octet: 25
|
|
||||||
custom_bind_mounts: []
|
|
||||||
extra_hosts: []
|
|
||||||
extra_env: []
|
|
||||||
'so-influxdb':
|
'so-influxdb':
|
||||||
final_octet: 26
|
final_octet: 26
|
||||||
port_bindings:
|
port_bindings:
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
{% from 'docker/docker.map.jinja' import DOCKER %}
|
{% from 'docker/docker.map.jinja' import DOCKER %}
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
|
|
||||||
# include ssl since docker service requires the intca
|
# docker service requires the ca.crt
|
||||||
include:
|
include:
|
||||||
- ssl
|
- ca
|
||||||
|
|
||||||
dockergroup:
|
dockergroup:
|
||||||
group.present:
|
group.present:
|
||||||
@@ -89,10 +89,9 @@ docker_running:
|
|||||||
- enable: True
|
- enable: True
|
||||||
- watch:
|
- watch:
|
||||||
- file: docker_daemon
|
- file: docker_daemon
|
||||||
- x509: trusttheca
|
|
||||||
- require:
|
- require:
|
||||||
- file: docker_daemon
|
- file: docker_daemon
|
||||||
- x509: trusttheca
|
- file: trusttheca
|
||||||
|
|
||||||
|
|
||||||
# Reserve OS ports for Docker proxy in case boot settings are not already applied/present
|
# Reserve OS ports for Docker proxy in case boot settings are not already applied/present
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ docker:
|
|||||||
forcedType: "[]string"
|
forcedType: "[]string"
|
||||||
so-elastic-fleet: *dockerOptions
|
so-elastic-fleet: *dockerOptions
|
||||||
so-elasticsearch: *dockerOptions
|
so-elasticsearch: *dockerOptions
|
||||||
so-idstools: *dockerOptions
|
|
||||||
so-influxdb: *dockerOptions
|
so-influxdb: *dockerOptions
|
||||||
so-kibana: *dockerOptions
|
so-kibana: *dockerOptions
|
||||||
so-kratos: *dockerOptions
|
so-kratos: *dockerOptions
|
||||||
@@ -102,4 +101,4 @@ docker:
|
|||||||
multiline: True
|
multiline: True
|
||||||
forcedType: "[]string"
|
forcedType: "[]string"
|
||||||
so-zeek: *dockerOptions
|
so-zeek: *dockerOptions
|
||||||
so-kafka: *dockerOptions
|
so-kafka: *dockerOptions
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ so-elastalert:
|
|||||||
- watch:
|
- watch:
|
||||||
- file: elastaconf
|
- file: elastaconf
|
||||||
- onlyif:
|
- onlyif:
|
||||||
- "so-elasticsearch-query / | jq -r '.version.number[0:1]' | grep -q 8" {# only run this state if elasticsearch is version 8 #}
|
- "so-elasticsearch-query / | jq -r '.version.number[0:1]' | grep -q 9" {# only run this state if elasticsearch is version 9 #}
|
||||||
|
|
||||||
delete_so-elastalert_so-status.disabled:
|
delete_so-elastalert_so-status.disabled:
|
||||||
file.uncomment:
|
file.uncomment:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{% from 'docker/docker.map.jinja' import DOCKER %}
|
{% from 'docker/docker.map.jinja' import DOCKER %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
|
- ca
|
||||||
- elasticagent.config
|
- elasticagent.config
|
||||||
- elasticagent.sostatus
|
- elasticagent.sostatus
|
||||||
|
|
||||||
@@ -55,8 +56,10 @@ so-elastic-agent:
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
- require:
|
- require:
|
||||||
- file: create-elastic-agent-config
|
- file: create-elastic-agent-config
|
||||||
|
- file: trusttheca
|
||||||
- watch:
|
- watch:
|
||||||
- file: create-elastic-agent-config
|
- file: create-elastic-agent-config
|
||||||
|
- file: trusttheca
|
||||||
|
|
||||||
delete_so-elastic-agent_so-status.disabled:
|
delete_so-elastic-agent_so-status.disabled:
|
||||||
file.uncomment:
|
file.uncomment:
|
||||||
|
|||||||
34
salt/elasticfleet/config.map.jinja
Normal file
34
salt/elasticfleet/config.map.jinja
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{# 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 'elasticfleet/map.jinja' import ELASTICFLEETMERGED %}
|
||||||
|
|
||||||
|
{# advanced config_yaml options for elasticfleet logstash output #}
|
||||||
|
{% set ADV_OUTPUT_LOGSTASH_RAW = ELASTICFLEETMERGED.config.outputs.logstash %}
|
||||||
|
{% set ADV_OUTPUT_LOGSTASH = {} %}
|
||||||
|
{% for k, v in ADV_OUTPUT_LOGSTASH_RAW.items() %}
|
||||||
|
{% if v != "" and v is not none %}
|
||||||
|
{% if k == 'queue_mem_events' %}
|
||||||
|
{# rename queue_mem_events queue.mem.events #}
|
||||||
|
{% do ADV_OUTPUT_LOGSTASH.update({'queue.mem.events':v}) %}
|
||||||
|
{% elif k == 'loadbalance' %}
|
||||||
|
{% if v %}
|
||||||
|
{# only include loadbalance config when its True #}
|
||||||
|
{% do ADV_OUTPUT_LOGSTASH.update({k:v}) %}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% do ADV_OUTPUT_LOGSTASH.update({k:v}) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% set LOGSTASH_CONFIG_YAML_RAW = [] %}
|
||||||
|
{% if ADV_OUTPUT_LOGSTASH %}
|
||||||
|
{% for k, v in ADV_OUTPUT_LOGSTASH.items() %}
|
||||||
|
{% do LOGSTASH_CONFIG_YAML_RAW.append(k ~ ': ' ~ v) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% set LOGSTASH_CONFIG_YAML = LOGSTASH_CONFIG_YAML_RAW | join('\\n') if LOGSTASH_CONFIG_YAML_RAW else '' %}
|
||||||
@@ -95,6 +95,9 @@ soresourcesrepoclone:
|
|||||||
- rev: 'main'
|
- rev: 'main'
|
||||||
- depth: 1
|
- depth: 1
|
||||||
- force_reset: True
|
- force_reset: True
|
||||||
|
- retry:
|
||||||
|
attempts: 3
|
||||||
|
interval: 10
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
elasticdefendconfdir:
|
elasticdefendconfdir:
|
||||||
|
|||||||
@@ -10,12 +10,19 @@ elasticfleet:
|
|||||||
grid_enrollment: ''
|
grid_enrollment: ''
|
||||||
defend_filters:
|
defend_filters:
|
||||||
enable_auto_configuration: False
|
enable_auto_configuration: False
|
||||||
|
outputs:
|
||||||
|
logstash:
|
||||||
|
bulk_max_size: ''
|
||||||
|
worker: ''
|
||||||
|
queue_mem_events: ''
|
||||||
|
timeout: ''
|
||||||
|
loadbalance: False
|
||||||
|
compression_level: ''
|
||||||
subscription_integrations: False
|
subscription_integrations: False
|
||||||
auto_upgrade_integrations: False
|
auto_upgrade_integrations: False
|
||||||
logging:
|
logging:
|
||||||
zeek:
|
zeek:
|
||||||
excluded:
|
excluded:
|
||||||
- analyzer
|
|
||||||
- broker
|
- broker
|
||||||
- capture_loss
|
- capture_loss
|
||||||
- cluster
|
- cluster
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
{% set SERVICETOKEN = salt['pillar.get']('elasticfleet:config:server:es_token','') %}
|
{% set SERVICETOKEN = salt['pillar.get']('elasticfleet:config:server:es_token','') %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
|
- ca
|
||||||
|
- logstash.ssl
|
||||||
|
- elasticfleet.ssl
|
||||||
- elasticfleet.config
|
- elasticfleet.config
|
||||||
- elasticfleet.sostatus
|
- elasticfleet.sostatus
|
||||||
- ssl
|
|
||||||
|
|
||||||
{% if grains.role not in ['so-fleet'] %}
|
{% if grains.role not in ['so-fleet'] %}
|
||||||
# Wait for Elasticsearch to be ready - no reason to try running Elastic Fleet server if ES is not ready
|
# Wait for Elasticsearch to be ready - no reason to try running Elastic Fleet server if ES is not ready
|
||||||
@@ -32,6 +34,17 @@ so-elastic-fleet-auto-configure-logstash-outputs:
|
|||||||
- retry:
|
- retry:
|
||||||
attempts: 4
|
attempts: 4
|
||||||
interval: 30
|
interval: 30
|
||||||
|
|
||||||
|
{# Separate from above in order to catch elasticfleet-logstash.crt changes and force update to fleet output policy #}
|
||||||
|
so-elastic-fleet-auto-configure-logstash-outputs-force:
|
||||||
|
cmd.run:
|
||||||
|
- name: /usr/sbin/so-elastic-fleet-outputs-update --certs
|
||||||
|
- retry:
|
||||||
|
attempts: 4
|
||||||
|
interval: 30
|
||||||
|
- onchanges:
|
||||||
|
- x509: etc_elasticfleet_logstash_crt
|
||||||
|
- x509: elasticfleet_kafka_crt
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# If enabled, automatically update Fleet Server URLs & ES Connection
|
# If enabled, automatically update Fleet Server URLs & ES Connection
|
||||||
@@ -122,6 +135,11 @@ so-elastic-fleet:
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
- watch:
|
- watch:
|
||||||
|
- file: trusttheca
|
||||||
|
- x509: etc_elasticfleet_key
|
||||||
|
- x509: etc_elasticfleet_crt
|
||||||
|
- require:
|
||||||
|
- file: trusttheca
|
||||||
- x509: etc_elasticfleet_key
|
- x509: etc_elasticfleet_key
|
||||||
- x509: etc_elasticfleet_crt
|
- x509: etc_elasticfleet_crt
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{%- raw -%}
|
{%- raw -%}
|
||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "import-zeek-logs",
|
"name": "import-zeek-logs",
|
||||||
@@ -10,19 +10,31 @@
|
|||||||
"description": "Zeek Import logs",
|
"description": "Zeek Import logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/import/*/zeek/logs/*.log"
|
"/nsm/import/*/zeek/logs/*.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "import",
|
"data_stream.dataset": "import",
|
||||||
"tags": [],
|
"pipeline": "",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": ["({%- endraw -%}{{ ELASTICFLEETMERGED.logging.zeek.excluded | join('|') }}{%- raw -%}).log$"],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- dissect:\n tokenizer: \"/nsm/import/%{import.id}/zeek/logs/%{import.file}\"\n field: \"log.file.path\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"import.file\").slice(0,-4);\n event.Put(\"@metadata.pipeline\", \"zeek.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: zeek\n imported: true\n- add_tags:\n tags: \"ics\"\n when:\n regexp:\n import.file: \"^bacnet*|^bsap*|^cip*|^cotp*|^dnp3*|^ecat*|^enip*|^modbus*|^opcua*|^profinet*|^s7comm*\"",
|
"processors": "- dissect:\n tokenizer: \"/nsm/import/%{import.id}/zeek/logs/%{import.file}\"\n field: \"log.file.path\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"import.file\").slice(0,-4);\n event.Put(\"@metadata.pipeline\", \"zeek.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: zeek\n imported: true\n- add_tags:\n tags: \"ics\"\n when:\n regexp:\n import.file: \"^bacnet*|^bsap*|^cip*|^cotp*|^dnp3*|^ecat*|^enip*|^modbus*|^opcua*|^profinet*|^s7comm*\"",
|
||||||
"custom": "exclude_files: [\"{%- endraw -%}{{ ELASTICFLEETMERGED.logging.zeek.excluded | join('|') }}{%- raw -%}.log$\"]\n"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,36 +11,51 @@
|
|||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "kratos-logs",
|
"name": "kratos-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Kratos logs",
|
"description": "Kratos logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/kratos/kratos.log"
|
"/opt/so/log/kratos/kratos.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "kratos",
|
"data_stream.dataset": "kratos",
|
||||||
"tags": ["so-kratos"],
|
"pipeline": "kratos",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
{%- if valid_identities -%}
|
{%- if valid_identities -%}
|
||||||
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- add_fields:\n target: event\n fields:\n category: iam\n module: kratos\n- if:\n has_fields:\n - identity_id\n then:{% for id, email in identities %}\n - if:\n equals:\n identity_id: \"{{ id }}\"\n then:\n - add_fields:\n target: ''\n fields:\n user.name: \"{{ email }}\"{% endfor %}",
|
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- add_fields:\n target: event\n fields:\n category: iam\n module: kratos\n- if:\n has_fields:\n - identity_id\n then:{% for id, email in identities %}\n - if:\n equals:\n identity_id: \"{{ id }}\"\n then:\n - add_fields:\n target: ''\n fields:\n user.name: \"{{ email }}\"{% endfor %}",
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- add_fields:\n target: event\n fields:\n category: iam\n module: kratos",
|
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- add_fields:\n target: event\n fields:\n category: iam\n module: kratos",
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
"custom": "pipeline: kratos"
|
"tags": [
|
||||||
|
"so-kratos"
|
||||||
|
],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,28 +2,38 @@
|
|||||||
{%- raw -%}
|
{%- raw -%}
|
||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"id": "zeek-logs",
|
|
||||||
"name": "zeek-logs",
|
"name": "zeek-logs",
|
||||||
"namespace": "so",
|
"namespace": "so",
|
||||||
"description": "Zeek logs",
|
"description": "Zeek logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/zeek/logs/current/*.log"
|
"/nsm/zeek/logs/current/*.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "zeek",
|
"data_stream.dataset": "zeek",
|
||||||
"tags": [],
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": ["({%- endraw -%}{{ ELASTICFLEETMERGED.logging.zeek.excluded | join('|') }}{%- raw -%}).log$"],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- dissect:\n tokenizer: \"/nsm/zeek/logs/current/%{pipeline}.log\"\n field: \"log.file.path\"\n trim_chars: \".log\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"pipeline\");\n event.Put(\"@metadata.pipeline\", \"zeek.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: zeek\n- add_tags:\n tags: \"ics\"\n when:\n regexp:\n pipeline: \"^bacnet*|^bsap*|^cip*|^cotp*|^dnp3*|^ecat*|^enip*|^modbus*|^opcua*|^profinet*|^s7comm*\"",
|
"processors": "- dissect:\n tokenizer: \"/nsm/zeek/logs/current/%{pipeline}.log\"\n field: \"log.file.path\"\n trim_chars: \".log\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"pipeline\");\n event.Put(\"@metadata.pipeline\", \"zeek.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: zeek\n- add_tags:\n tags: \"ics\"\n when:\n regexp:\n pipeline: \"^bacnet*|^bsap*|^cip*|^cotp*|^dnp3*|^ecat*|^enip*|^modbus*|^opcua*|^profinet*|^s7comm*\"",
|
||||||
"custom": "exclude_files: [\"{%- endraw -%}{{ ELASTICFLEETMERGED.logging.zeek.excluded | join('|') }}{%- raw -%}.log$\"]\n"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,4 +41,4 @@
|
|||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
{%- endraw -%}
|
{%- endraw -%}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
"package": {
|
"package": {
|
||||||
"name": "endpoint",
|
"name": "endpoint",
|
||||||
"title": "Elastic Defend",
|
"title": "Elastic Defend",
|
||||||
"version": "8.18.1",
|
"version": "9.0.2",
|
||||||
"requires_root": true
|
"requires_root": true
|
||||||
},
|
},
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|||||||
@@ -1,26 +1,43 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "hydra-logs",
|
"name": "hydra-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Hydra logs",
|
"description": "Hydra logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/hydra/hydra.log"
|
"/opt/so/log/hydra/hydra.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "hydra",
|
"data_stream.dataset": "hydra",
|
||||||
"tags": ["so-hydra"],
|
"pipeline": "hydra",
|
||||||
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: iam\n module: hydra",
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
"custom": "pipeline: hydra"
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
|
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- add_fields:\n target: event\n fields:\n category: iam\n module: hydra",
|
||||||
|
"tags": [
|
||||||
|
"so-hydra"
|
||||||
|
],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"ignore_older": "72h",
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,3 +45,5 @@
|
|||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,44 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "idh-logs",
|
"name": "idh-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "IDH integration",
|
"description": "IDH integration",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/idh/opencanary.log"
|
"/nsm/idh/opencanary.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "idh",
|
"data_stream.dataset": "idh",
|
||||||
"tags": [],
|
"pipeline": "common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "\n- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- convert:\n fields:\n - {from: \"logtype\", to: \"event.code\", type: \"string\"}\n- drop_fields:\n when:\n equals:\n event.code: \"1001\"\n fields: [\"src_host\", \"src_port\", \"dst_host\", \"dst_port\" ]\n ignore_missing: true\n- rename:\n fields:\n - from: \"src_host\"\n to: \"source.ip\"\n - from: \"src_port\"\n to: \"source.port\"\n - from: \"dst_host\"\n to: \"destination.host\"\n - from: \"dst_port\"\n to: \"destination.port\"\n ignore_missing: true\n- drop_fields:\n fields: '[\"prospector\", \"input\", \"offset\", \"beat\"]'\n- add_fields:\n target: event\n fields:\n category: host\n module: opencanary",
|
"processors": "\n- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n add_error_key: true\n- convert:\n fields:\n - {from: \"logtype\", to: \"event.code\", type: \"string\"}\n- drop_fields:\n when:\n equals:\n event.code: \"1001\"\n fields: [\"src_host\", \"src_port\", \"dst_host\", \"dst_port\" ]\n ignore_missing: true\n- rename:\n fields:\n - from: \"src_host\"\n to: \"source.ip\"\n - from: \"src_port\"\n to: \"source.port\"\n - from: \"dst_host\"\n to: \"destination.host\"\n - from: \"dst_port\"\n to: \"destination.port\"\n ignore_missing: true\n- drop_fields:\n fields: '[\"prospector\", \"input\", \"offset\", \"beat\"]'\n- add_fields:\n target: event\n fields:\n category: host\n module: opencanary",
|
||||||
"custom": "pipeline: common"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,46 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "import-evtx-logs",
|
"name": "import-evtx-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Import Windows EVTX logs",
|
"description": "Import Windows EVTX logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
"vars": {},
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/import/*/evtx/*.json"
|
"/nsm/import/*/evtx/*.json"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "import",
|
"data_stream.dataset": "import",
|
||||||
"custom": "",
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- dissect:\n tokenizer: \"/nsm/import/%{import.id}/evtx/%{import.file}\"\n field: \"log.file.path\"\n target_prefix: \"\"\n- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n- drop_fields:\n fields: [\"host\"]\n ignore_missing: true\n- add_fields:\n target: data_stream\n fields:\n type: logs\n dataset: system.security\n- add_fields:\n target: event\n fields:\n dataset: system.security\n module: system\n imported: true\n- add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-system.security-2.6.1\n- if:\n equals:\n winlog.channel: 'Microsoft-Windows-Sysmon/Operational'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: windows.sysmon_operational\n - add_fields:\n target: event\n fields:\n dataset: windows.sysmon_operational\n module: windows\n imported: true\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-windows.sysmon_operational-3.1.2\n- if:\n equals:\n winlog.channel: 'Application'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: system.application\n - add_fields:\n target: event\n fields:\n dataset: system.application\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-system.application-2.6.1\n- if:\n equals:\n winlog.channel: 'System'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: system.system\n - add_fields:\n target: event\n fields:\n dataset: system.system\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-system.system-2.6.1\n \n- if:\n equals:\n winlog.channel: 'Microsoft-Windows-PowerShell/Operational'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: windows.powershell_operational\n - add_fields:\n target: event\n fields:\n dataset: windows.powershell_operational\n module: windows\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-windows.powershell_operational-3.1.2\n- add_fields:\n target: data_stream\n fields:\n dataset: import",
|
"processors": "- dissect:\n tokenizer: \"/nsm/import/%{import.id}/evtx/%{import.file}\"\n field: \"log.file.path\"\n target_prefix: \"\"\n- decode_json_fields:\n fields: [\"message\"]\n target: \"\"\n- drop_fields:\n fields: [\"host\"]\n ignore_missing: true\n- add_fields:\n target: data_stream\n fields:\n type: logs\n dataset: system.security\n- add_fields:\n target: event\n fields:\n dataset: system.security\n module: system\n imported: true\n- add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-system.security-2.6.1\n- if:\n equals:\n winlog.channel: 'Microsoft-Windows-Sysmon/Operational'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: windows.sysmon_operational\n - add_fields:\n target: event\n fields:\n dataset: windows.sysmon_operational\n module: windows\n imported: true\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-windows.sysmon_operational-3.1.2\n- if:\n equals:\n winlog.channel: 'Application'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: system.application\n - add_fields:\n target: event\n fields:\n dataset: system.application\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-system.application-2.6.1\n- if:\n equals:\n winlog.channel: 'System'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: system.system\n - add_fields:\n target: event\n fields:\n dataset: system.system\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-system.system-2.6.1\n \n- if:\n equals:\n winlog.channel: 'Microsoft-Windows-PowerShell/Operational'\n then: \n - add_fields:\n target: data_stream\n fields:\n dataset: windows.powershell_operational\n - add_fields:\n target: event\n fields:\n dataset: windows.powershell_operational\n module: windows\n - add_fields:\n target: \"@metadata\"\n fields:\n pipeline: logs-windows.powershell_operational-3.1.2\n- add_fields:\n target: data_stream\n fields:\n dataset: import",
|
||||||
"tags": [
|
"tags": [
|
||||||
"import"
|
"import"
|
||||||
]
|
],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"ignore_older": "72h",
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,45 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "import-suricata-logs",
|
"name": "import-suricata-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Import Suricata logs",
|
"description": "Import Suricata logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/import/*/suricata/eve*.json"
|
"/nsm/import/*/suricata/eve*.json"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "import",
|
"data_stream.dataset": "import",
|
||||||
|
"pipeline": "suricata.common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
|
"processors": "- add_fields:\n target: event\n fields:\n category: network\n module: suricata\n imported: true\n- dissect:\n tokenizer: \"/nsm/import/%{import.id}/suricata/%{import.file}\"\n field: \"log.file.path\"\n target_prefix: \"\"\n",
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"processors": "- add_fields:\n target: event\n fields:\n category: network\n module: suricata\n imported: true\n- dissect:\n tokenizer: \"/nsm/import/%{import.id}/suricata/%{import.file}\"\n field: \"log.file.path\"\n target_prefix: \"\"",
|
"recursive_glob": true,
|
||||||
"custom": "pipeline: suricata.common"
|
"ignore_older": "72h",
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "rita-logs",
|
"name": "rita-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "RITA Logs",
|
"description": "RITA Logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
"vars": {},
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
@@ -20,15 +19,28 @@
|
|||||||
"/nsm/rita/exploded-dns.csv",
|
"/nsm/rita/exploded-dns.csv",
|
||||||
"/nsm/rita/long-connections.csv"
|
"/nsm/rita/long-connections.csv"
|
||||||
],
|
],
|
||||||
"exclude_files": [],
|
|
||||||
"ignore_older": "72h",
|
|
||||||
"data_stream.dataset": "rita",
|
"data_stream.dataset": "rita",
|
||||||
"tags": [],
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- dissect:\n tokenizer: \"/nsm/rita/%{pipeline}.csv\"\n field: \"log.file.path\"\n trim_chars: \".csv\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"pipeline\").split(\"-\");\n if (pl.length > 1) {\n pl = pl[1];\n }\n else {\n pl = pl[0];\n }\n event.Put(\"@metadata.pipeline\", \"rita.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: rita",
|
"processors": "- dissect:\n tokenizer: \"/nsm/rita/%{pipeline}.csv\"\n field: \"log.file.path\"\n trim_chars: \".csv\"\n target_prefix: \"\"\n- script:\n lang: javascript\n source: >\n function process(event) {\n var pl = event.Get(\"pipeline\").split(\"-\");\n if (pl.length > 1) {\n pl = pl[1];\n }\n else {\n pl = pl[0];\n }\n event.Put(\"@metadata.pipeline\", \"rita.\" + pl);\n }\n- add_fields:\n target: event\n fields:\n category: network\n module: rita",
|
||||||
"custom": "exclude_lines: ['^Score', '^Source', '^Domain', '^No results']"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"ignore_older": "72h",
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"force": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,41 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "so-ip-mappings",
|
"name": "so-ip-mappings",
|
||||||
"namespace": "so",
|
|
||||||
"description": "IP Description mappings",
|
"description": "IP Description mappings",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
"vars": {},
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/custom-mappings/ip-descriptions.csv"
|
"/nsm/custom-mappings/ip-descriptions.csv"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "hostnamemappings",
|
"data_stream.dataset": "hostnamemappings",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
|
"processors": "- decode_csv_fields:\n fields:\n message: decoded.csv\n separator: \",\"\n ignore_missing: false\n overwrite_keys: true\n trim_leading_space: true\n fail_on_error: true\n\n- extract_array:\n field: decoded.csv\n mappings:\n so.ip_address: '0'\n so.description: '1'\n\n- script:\n lang: javascript\n source: >\n function process(event) {\n var ip = event.Get('so.ip_address');\n var validIpRegex = /^((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)$/\n if (!validIpRegex.test(ip)) {\n event.Cancel();\n }\n }\n- fingerprint:\n fields: [\"so.ip_address\"]\n target_field: \"@metadata._id\"\n",
|
||||||
"tags": [
|
"tags": [
|
||||||
"so-ip-mappings"
|
"so-ip-mappings"
|
||||||
],
|
],
|
||||||
"processors": "- decode_csv_fields:\n fields:\n message: decoded.csv\n separator: \",\"\n ignore_missing: false\n overwrite_keys: true\n trim_leading_space: true\n fail_on_error: true\n\n- extract_array:\n field: decoded.csv\n mappings:\n so.ip_address: '0'\n so.description: '1'\n\n- script:\n lang: javascript\n source: >\n function process(event) {\n var ip = event.Get('so.ip_address');\n var validIpRegex = /^((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)$/\n if (!validIpRegex.test(ip)) {\n event.Cancel();\n }\n }\n- fingerprint:\n fields: [\"so.ip_address\"]\n target_field: \"@metadata._id\"\n",
|
"recursive_glob": true,
|
||||||
"custom": ""
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,5 +43,3 @@
|
|||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,44 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "soc-auth-sync-logs",
|
"name": "soc-auth-sync-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Security Onion - Elastic Auth Sync - Logs",
|
"description": "Security Onion - Elastic Auth Sync - Logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/soc/sync.log"
|
"/opt/so/log/soc/sync.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "soc",
|
"data_stream.dataset": "soc",
|
||||||
"tags": ["so-soc"],
|
"pipeline": "common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- dissect:\n tokenizer: \"%{event.action}\"\n field: \"message\"\n target_prefix: \"\"\n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: auth_sync",
|
"processors": "- dissect:\n tokenizer: \"%{event.action}\"\n field: \"message\"\n target_prefix: \"\"\n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: auth_sync",
|
||||||
"custom": "pipeline: common"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,48 @@
|
|||||||
{
|
{
|
||||||
"policy_id": "so-grid-nodes_general",
|
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "soc-detections-logs",
|
"name": "soc-detections-logs",
|
||||||
"description": "Security Onion Console - Detections Logs",
|
"description": "Security Onion Console - Detections Logs",
|
||||||
|
"policy_id": "so-grid-nodes_general",
|
||||||
"namespace": "so",
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/soc/detections_runtime-status_sigma.log",
|
"/opt/so/log/soc/detections_runtime-status_sigma.log",
|
||||||
"/opt/so/log/soc/detections_runtime-status_yara.log"
|
"/opt/so/log/soc/detections_runtime-status_yara.log"
|
||||||
],
|
],
|
||||||
"exclude_files": [],
|
|
||||||
"ignore_older": "72h",
|
|
||||||
"data_stream.dataset": "soc",
|
"data_stream.dataset": "soc",
|
||||||
|
"pipeline": "common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
|
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"soc\"\n process_array: true\n max_depth: 2\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: detections\n- rename:\n fields:\n - from: \"soc.fields.sourceIp\"\n to: \"source.ip\"\n - from: \"soc.fields.status\"\n to: \"http.response.status_code\"\n - from: \"soc.fields.method\"\n to: \"http.request.method\"\n - from: \"soc.fields.path\"\n to: \"url.path\"\n - from: \"soc.message\"\n to: \"event.action\"\n - from: \"soc.level\"\n to: \"log.level\"\n ignore_missing: true",
|
||||||
"tags": [
|
"tags": [
|
||||||
"so-soc"
|
"so-soc"
|
||||||
],
|
],
|
||||||
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"soc\"\n process_array: true\n max_depth: 2\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: detections\n- rename:\n fields:\n - from: \"soc.fields.sourceIp\"\n to: \"source.ip\"\n - from: \"soc.fields.status\"\n to: \"http.response.status_code\"\n - from: \"soc.fields.method\"\n to: \"http.request.method\"\n - from: \"soc.fields.path\"\n to: \"url.path\"\n - from: \"soc.message\"\n to: \"event.action\"\n - from: \"soc.level\"\n to: \"log.level\"\n ignore_missing: true",
|
"recursive_glob": true,
|
||||||
"custom": "pipeline: common"
|
"ignore_older": "72h",
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,46 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "soc-salt-relay-logs",
|
"name": "soc-salt-relay-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Security Onion - Salt Relay - Logs",
|
"description": "Security Onion - Salt Relay - Logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/soc/salt-relay.log"
|
"/opt/so/log/soc/salt-relay.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "soc",
|
"data_stream.dataset": "soc",
|
||||||
"tags": ["so-soc"],
|
"pipeline": "common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- dissect:\n tokenizer: \"%{soc.ts} | %{event.action}\"\n field: \"message\"\n target_prefix: \"\"\n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: salt_relay",
|
"processors": "- dissect:\n tokenizer: \"%{soc.ts} | %{event.action}\"\n field: \"message\"\n target_prefix: \"\"\n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: salt_relay",
|
||||||
"custom": "pipeline: common"
|
"tags": [
|
||||||
|
"so-soc"
|
||||||
|
],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,44 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "soc-sensoroni-logs",
|
"name": "soc-sensoroni-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Security Onion - Sensoroni - Logs",
|
"description": "Security Onion - Sensoroni - Logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/sensoroni/sensoroni.log"
|
"/opt/so/log/sensoroni/sensoroni.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "soc",
|
"data_stream.dataset": "soc",
|
||||||
"tags": [],
|
"pipeline": "common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"sensoroni\"\n process_array: true\n max_depth: 2\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: sensoroni\n- rename:\n fields:\n - from: \"sensoroni.fields.sourceIp\"\n to: \"source.ip\"\n - from: \"sensoroni.fields.status\"\n to: \"http.response.status_code\"\n - from: \"sensoroni.fields.method\"\n to: \"http.request.method\"\n - from: \"sensoroni.fields.path\"\n to: \"url.path\"\n - from: \"sensoroni.message\"\n to: \"event.action\"\n - from: \"sensoroni.level\"\n to: \"log.level\"\n ignore_missing: true",
|
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"sensoroni\"\n process_array: true\n max_depth: 2\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: sensoroni\n- rename:\n fields:\n - from: \"sensoroni.fields.sourceIp\"\n to: \"source.ip\"\n - from: \"sensoroni.fields.status\"\n to: \"http.response.status_code\"\n - from: \"sensoroni.fields.method\"\n to: \"http.request.method\"\n - from: \"sensoroni.fields.path\"\n to: \"url.path\"\n - from: \"sensoroni.message\"\n to: \"event.action\"\n - from: \"sensoroni.level\"\n to: \"log.level\"\n ignore_missing: true",
|
||||||
"custom": "pipeline: common"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,46 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "soc-server-logs",
|
"name": "soc-server-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Security Onion Console Logs",
|
"description": "Security Onion Console Logs",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/opt/so/log/soc/sensoroni-server.log"
|
"/opt/so/log/soc/sensoroni-server.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "soc",
|
"data_stream.dataset": "soc",
|
||||||
"tags": ["so-soc"],
|
"pipeline": "common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"soc\"\n process_array: true\n max_depth: 2\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: server\n- rename:\n fields:\n - from: \"soc.fields.sourceIp\"\n to: \"source.ip\"\n - from: \"soc.fields.status\"\n to: \"http.response.status_code\"\n - from: \"soc.fields.method\"\n to: \"http.request.method\"\n - from: \"soc.fields.path\"\n to: \"url.path\"\n - from: \"soc.message\"\n to: \"event.action\"\n - from: \"soc.level\"\n to: \"log.level\"\n ignore_missing: true",
|
"processors": "- decode_json_fields:\n fields: [\"message\"]\n target: \"soc\"\n process_array: true\n max_depth: 2\n add_error_key: true \n- add_fields:\n target: event\n fields:\n category: host\n module: soc\n dataset_temp: server\n- rename:\n fields:\n - from: \"soc.fields.sourceIp\"\n to: \"source.ip\"\n - from: \"soc.fields.status\"\n to: \"http.response.status_code\"\n - from: \"soc.fields.method\"\n to: \"http.request.method\"\n - from: \"soc.fields.path\"\n to: \"url.path\"\n - from: \"soc.message\"\n to: \"event.action\"\n - from: \"soc.level\"\n to: \"log.level\"\n ignore_missing: true",
|
||||||
"custom": "pipeline: common"
|
"tags": [
|
||||||
|
"so-soc"
|
||||||
|
],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,44 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "strelka-logs",
|
"name": "strelka-logs",
|
||||||
"namespace": "so",
|
"description": "Strelka Logs",
|
||||||
"description": "Strelka logs",
|
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/strelka/log/strelka.log"
|
"/nsm/strelka/log/strelka.log"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "strelka",
|
"data_stream.dataset": "strelka",
|
||||||
"tags": [],
|
"pipeline": "strelka.file",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- add_fields:\n target: event\n fields:\n category: file\n module: strelka",
|
"processors": "- add_fields:\n target: event\n fields:\n category: file\n module: strelka",
|
||||||
"custom": "pipeline: strelka.file"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,44 @@
|
|||||||
{
|
{
|
||||||
"package": {
|
"package": {
|
||||||
"name": "log",
|
"name": "filestream",
|
||||||
"version": ""
|
"version": ""
|
||||||
},
|
},
|
||||||
"name": "suricata-logs",
|
"name": "suricata-logs",
|
||||||
"namespace": "so",
|
|
||||||
"description": "Suricata integration",
|
"description": "Suricata integration",
|
||||||
"policy_id": "so-grid-nodes_general",
|
"policy_id": "so-grid-nodes_general",
|
||||||
|
"namespace": "so",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"logs-logfile": {
|
"filestream-filestream": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"streams": {
|
"streams": {
|
||||||
"log.logs": {
|
"filestream.generic": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"vars": {
|
"vars": {
|
||||||
"paths": [
|
"paths": [
|
||||||
"/nsm/suricata/eve*.json"
|
"/nsm/suricata/eve*.json"
|
||||||
],
|
],
|
||||||
"data_stream.dataset": "suricata",
|
"data_stream.dataset": "filestream.generic",
|
||||||
"tags": [],
|
"pipeline": "suricata.common",
|
||||||
|
"parsers": "#- ndjson:\n# target: \"\"\n# message_key: msg\n#- multiline:\n# type: count\n# count_lines: 3\n",
|
||||||
|
"exclude_files": [
|
||||||
|
"\\.gz$"
|
||||||
|
],
|
||||||
|
"include_files": [],
|
||||||
"processors": "- add_fields:\n target: event\n fields:\n category: network\n module: suricata",
|
"processors": "- add_fields:\n target: event\n fields:\n category: network\n module: suricata",
|
||||||
"custom": "pipeline: suricata.common"
|
"tags": [],
|
||||||
|
"recursive_glob": true,
|
||||||
|
"clean_inactive": -1,
|
||||||
|
"harvester_limit": 0,
|
||||||
|
"fingerprint": false,
|
||||||
|
"fingerprint_offset": 0,
|
||||||
|
"fingerprint_length": "64",
|
||||||
|
"file_identity_native": true,
|
||||||
|
"exclude_lines": [],
|
||||||
|
"include_lines": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"force": true
|
"force": true
|
||||||
}
|
}
|
||||||
@@ -2,26 +2,32 @@
|
|||||||
# or more contributor license agreements. Licensed under the Elastic License 2.0; you may not use
|
# or more contributor license agreements. Licensed under the Elastic License 2.0; you may not use
|
||||||
# this file except in compliance with the Elastic License 2.0.
|
# this file except in compliance with the Elastic License 2.0.
|
||||||
|
|
||||||
{%- set GRIDNODETOKENGENERAL = salt['pillar.get']('global:fleet_grid_enrollment_token_general') -%}
|
{% set GRIDNODETOKEN = salt['pillar.get']('global:fleet_grid_enrollment_token_general') -%}
|
||||||
{%- set GRIDNODETOKENHEAVY = salt['pillar.get']('global:fleet_grid_enrollment_token_heavy') -%}
|
{% if grains.role == 'so-heavynode' %}
|
||||||
|
{% set GRIDNODETOKEN = salt['pillar.get']('global:fleet_grid_enrollment_token_heavy') -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% set AGENT_STATUS = salt['service.available']('elastic-agent') %}
|
{% set AGENT_STATUS = salt['service.available']('elastic-agent') %}
|
||||||
{% if not AGENT_STATUS %}
|
{% set AGENT_EXISTS = salt['file.file_exists']('/opt/Elastic/Agent/elastic-agent') %}
|
||||||
|
|
||||||
{% if grains.role not in ['so-heavynode'] %}
|
{% if not AGENT_STATUS or not AGENT_EXISTS %}
|
||||||
run_installer:
|
|
||||||
cmd.script:
|
|
||||||
- name: salt://elasticfleet/files/so_agent-installers/so-elastic-agent_linux_amd64
|
|
||||||
- cwd: /opt/so
|
|
||||||
- args: -token={{ GRIDNODETOKENGENERAL }}
|
|
||||||
- retry: True
|
|
||||||
{% else %}
|
|
||||||
run_installer:
|
|
||||||
cmd.script:
|
|
||||||
- name: salt://elasticfleet/files/so_agent-installers/so-elastic-agent_linux_amd64
|
|
||||||
- cwd: /opt/so
|
|
||||||
- args: -token={{ GRIDNODETOKENHEAVY }}
|
|
||||||
- retry: True
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
pull_agent_installer:
|
||||||
|
file.managed:
|
||||||
|
- name: /opt/so/so-elastic-agent_linux_amd64
|
||||||
|
- source: salt://elasticfleet/files/so_agent-installers/so-elastic-agent_linux_amd64
|
||||||
|
- mode: 755
|
||||||
|
- makedirs: True
|
||||||
|
|
||||||
|
run_installer:
|
||||||
|
cmd.run:
|
||||||
|
- name: ./so-elastic-agent_linux_amd64 -token={{ GRIDNODETOKEN }} -force
|
||||||
|
- cwd: /opt/so
|
||||||
|
- retry:
|
||||||
|
attempts: 3
|
||||||
|
interval: 20
|
||||||
|
|
||||||
|
cleanup_agent_installer:
|
||||||
|
file.absent:
|
||||||
|
- name: /opt/so/so-elastic-agent_linux_amd64
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
'azure_application_insights.app_state': 'azure.app_state',
|
'azure_application_insights.app_state': 'azure.app_state',
|
||||||
'azure_billing.billing': 'azure.billing',
|
'azure_billing.billing': 'azure.billing',
|
||||||
'azure_functions.metrics': 'azure.function',
|
'azure_functions.metrics': 'azure.function',
|
||||||
|
'azure_ai_foundry.metrics': 'azure.ai_foundry',
|
||||||
'azure_metrics.compute_vm_scaleset': 'azure.compute_vm_scaleset',
|
'azure_metrics.compute_vm_scaleset': 'azure.compute_vm_scaleset',
|
||||||
'azure_metrics.compute_vm': 'azure.compute_vm',
|
'azure_metrics.compute_vm': 'azure.compute_vm',
|
||||||
'azure_metrics.container_instance': 'azure.container_instance',
|
'azure_metrics.container_instance': 'azure.container_instance',
|
||||||
@@ -121,6 +122,9 @@
|
|||||||
"phases": {
|
"phases": {
|
||||||
"cold": {
|
"cold": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"allocate":{
|
||||||
|
"number_of_replicas": ""
|
||||||
|
},
|
||||||
"set_priority": {"priority": 0}
|
"set_priority": {"priority": 0}
|
||||||
},
|
},
|
||||||
"min_age": "60d"
|
"min_age": "60d"
|
||||||
@@ -137,12 +141,31 @@
|
|||||||
"max_age": "30d",
|
"max_age": "30d",
|
||||||
"max_primary_shard_size": "50gb"
|
"max_primary_shard_size": "50gb"
|
||||||
},
|
},
|
||||||
|
"forcemerge":{
|
||||||
|
"max_num_segments": ""
|
||||||
|
},
|
||||||
|
"shrink":{
|
||||||
|
"max_primary_shard_size": "",
|
||||||
|
"method": "COUNT",
|
||||||
|
"number_of_shards": ""
|
||||||
|
},
|
||||||
"set_priority": {"priority": 100}
|
"set_priority": {"priority": 100}
|
||||||
},
|
},
|
||||||
"min_age": "0ms"
|
"min_age": "0ms"
|
||||||
},
|
},
|
||||||
"warm": {
|
"warm": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"allocate": {
|
||||||
|
"number_of_replicas": ""
|
||||||
|
},
|
||||||
|
"forcemerge": {
|
||||||
|
"max_num_segments": ""
|
||||||
|
},
|
||||||
|
"shrink":{
|
||||||
|
"max_primary_shard_size": "",
|
||||||
|
"method": "COUNT",
|
||||||
|
"number_of_shards": ""
|
||||||
|
},
|
||||||
"set_priority": {"priority": 50}
|
"set_priority": {"priority": 50}
|
||||||
},
|
},
|
||||||
"min_age": "30d"
|
"min_age": "30d"
|
||||||
|
|||||||
@@ -50,6 +50,46 @@ elasticfleet:
|
|||||||
global: True
|
global: True
|
||||||
forcedType: bool
|
forcedType: bool
|
||||||
helpLink: elastic-fleet.html
|
helpLink: elastic-fleet.html
|
||||||
|
outputs:
|
||||||
|
logstash:
|
||||||
|
bulk_max_size:
|
||||||
|
description: The maximum number of events to bulk in a single Logstash request.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
helpLink: elastic-fleet.html
|
||||||
|
worker:
|
||||||
|
description: The number of workers per configured host publishing events.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: true
|
||||||
|
helpLink: elastic-fleet.html
|
||||||
|
queue_mem_events:
|
||||||
|
title: queued events
|
||||||
|
description: The number of events the queue can store. This value should be evenly divisible by the smaller of 'bulk_max_size' to avoid sending partial batches to the output.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
helpLink: elastic-fleet.html
|
||||||
|
timeout:
|
||||||
|
description: The number of seconds to wait for responses from the Logstash server before timing out. Eg 30s
|
||||||
|
regex: ^[0-9]+s$
|
||||||
|
advanced: True
|
||||||
|
global: True
|
||||||
|
helpLink: elastic-fleet.html
|
||||||
|
loadbalance:
|
||||||
|
description: If true and multiple Logstash hosts are configured, the output plugin load balances published events onto all Logstash hosts. If false, the output plugin sends all events to one host (determined at random) and switches to another host if the selected one becomes unresponsive.
|
||||||
|
forcedType: bool
|
||||||
|
advanced: True
|
||||||
|
global: True
|
||||||
|
helpLink: elastic-fleet.html
|
||||||
|
compression_level:
|
||||||
|
description: The gzip compression level. The compression level must be in the range of 1 (best speed) to 9 (best compression).
|
||||||
|
regex: ^[1-9]$
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
global: True
|
||||||
|
helpLink: elastic-fleet.html
|
||||||
server:
|
server:
|
||||||
custom_fqdn:
|
custom_fqdn:
|
||||||
description: Custom FQDN for Agents to connect to. One per line.
|
description: Custom FQDN for Agents to connect to. One per line.
|
||||||
|
|||||||
186
salt/elasticfleet/ssl.sls
Normal file
186
salt/elasticfleet/ssl.sls
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
# 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 'elasticfleet/map.jinja' import ELASTICFLEETMERGED %}
|
||||||
|
{% from 'ca/map.jinja' import CA %}
|
||||||
|
|
||||||
|
{% if GLOBALS.is_manager or GLOBALS.role in ['so-heavynode', 'so-fleet', 'so-receiver'] %}
|
||||||
|
|
||||||
|
{% if grains['role'] not in [ 'so-heavynode', 'so-receiver'] %}
|
||||||
|
# Start -- Elastic Fleet Host Cert
|
||||||
|
etc_elasticfleet_key:
|
||||||
|
x509.private_key_managed:
|
||||||
|
- name: /etc/pki/elasticfleet-server.key
|
||||||
|
- keysize: 4096
|
||||||
|
- backup: True
|
||||||
|
- new: True
|
||||||
|
{% if salt['file.file_exists']('/etc/pki/elasticfleet-server.key') -%}
|
||||||
|
- prereq:
|
||||||
|
- x509: etc_elasticfleet_crt
|
||||||
|
{%- endif %}
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
etc_elasticfleet_crt:
|
||||||
|
x509.certificate_managed:
|
||||||
|
- name: /etc/pki/elasticfleet-server.crt
|
||||||
|
- ca_server: {{ CA.server }}
|
||||||
|
- signing_policy: elasticfleet
|
||||||
|
- private_key: /etc/pki/elasticfleet-server.key
|
||||||
|
- CN: {{ GLOBALS.hostname }}
|
||||||
|
- subjectAltName: DNS:{{ GLOBALS.hostname }},DNS:{{ GLOBALS.url_base }},IP:{{ GLOBALS.node_ip }}{% if ELASTICFLEETMERGED.config.server.custom_fqdn | length > 0 %},DNS:{{ ELASTICFLEETMERGED.config.server.custom_fqdn | join(',DNS:') }}{% endif %}
|
||||||
|
- days_remaining: 7
|
||||||
|
- days_valid: 820
|
||||||
|
- backup: True
|
||||||
|
- timeout: 30
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
efperms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-server.key
|
||||||
|
- mode: 640
|
||||||
|
- group: 939
|
||||||
|
|
||||||
|
chownelasticfleetcrt:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-server.crt
|
||||||
|
- mode: 640
|
||||||
|
- user: 947
|
||||||
|
- group: 939
|
||||||
|
|
||||||
|
chownelasticfleetkey:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-server.key
|
||||||
|
- mode: 640
|
||||||
|
- user: 947
|
||||||
|
- group: 939
|
||||||
|
# End -- Elastic Fleet Host Cert
|
||||||
|
{% endif %} # endif is for not including HeavyNodes & Receivers
|
||||||
|
|
||||||
|
|
||||||
|
# Start -- Elastic Fleet Client Cert for Agent (Mutual Auth with Logstash Output)
|
||||||
|
etc_elasticfleet_agent_key:
|
||||||
|
x509.private_key_managed:
|
||||||
|
- name: /etc/pki/elasticfleet-agent.key
|
||||||
|
- keysize: 4096
|
||||||
|
- backup: True
|
||||||
|
- new: True
|
||||||
|
{% if salt['file.file_exists']('/etc/pki/elasticfleet-agent.key') -%}
|
||||||
|
- prereq:
|
||||||
|
- x509: etc_elasticfleet_agent_crt
|
||||||
|
{%- endif %}
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
etc_elasticfleet_agent_crt:
|
||||||
|
x509.certificate_managed:
|
||||||
|
- name: /etc/pki/elasticfleet-agent.crt
|
||||||
|
- ca_server: {{ CA.server }}
|
||||||
|
- signing_policy: elasticfleet
|
||||||
|
- private_key: /etc/pki/elasticfleet-agent.key
|
||||||
|
- CN: {{ GLOBALS.hostname }}
|
||||||
|
- days_remaining: 7
|
||||||
|
- days_valid: 820
|
||||||
|
- backup: True
|
||||||
|
- timeout: 30
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
cmd.run:
|
||||||
|
- name: "/usr/bin/openssl pkcs8 -in /etc/pki/elasticfleet-agent.key -topk8 -out /etc/pki/elasticfleet-agent.p8 -nocrypt"
|
||||||
|
- onchanges:
|
||||||
|
- x509: etc_elasticfleet_agent_key
|
||||||
|
|
||||||
|
efagentperms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-agent.key
|
||||||
|
- mode: 640
|
||||||
|
- group: 939
|
||||||
|
|
||||||
|
chownelasticfleetagentcrt:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-agent.crt
|
||||||
|
- mode: 640
|
||||||
|
- user: 947
|
||||||
|
- group: 939
|
||||||
|
|
||||||
|
chownelasticfleetagentkey:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-agent.key
|
||||||
|
- mode: 640
|
||||||
|
- user: 947
|
||||||
|
- group: 939
|
||||||
|
# End -- Elastic Fleet Client Cert for Agent (Mutual Auth with Logstash Output)
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if GLOBALS.role in ['so-manager', 'so-managerhype', 'so-managersearch', 'so-standalone'] %}
|
||||||
|
elasticfleet_kafka_key:
|
||||||
|
x509.private_key_managed:
|
||||||
|
- name: /etc/pki/elasticfleet-kafka.key
|
||||||
|
- keysize: 4096
|
||||||
|
- backup: True
|
||||||
|
- new: True
|
||||||
|
{% if salt['file.file_exists']('/etc/pki/elasticfleet-kafka.key') -%}
|
||||||
|
- prereq:
|
||||||
|
- x509: elasticfleet_kafka_crt
|
||||||
|
{%- endif %}
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
elasticfleet_kafka_crt:
|
||||||
|
x509.certificate_managed:
|
||||||
|
- name: /etc/pki/elasticfleet-kafka.crt
|
||||||
|
- ca_server: {{ CA.server }}
|
||||||
|
- signing_policy: kafka
|
||||||
|
- private_key: /etc/pki/elasticfleet-kafka.key
|
||||||
|
- CN: {{ GLOBALS.hostname }}
|
||||||
|
- subjectAltName: DNS:{{ GLOBALS.hostname }}, IP:{{ GLOBALS.node_ip }}
|
||||||
|
- days_remaining: 7
|
||||||
|
- days_valid: 820
|
||||||
|
- backup: True
|
||||||
|
- timeout: 30
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
elasticfleet_kafka_cert_perms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-kafka.crt
|
||||||
|
- mode: 640
|
||||||
|
- user: 947
|
||||||
|
- group: 939
|
||||||
|
|
||||||
|
elasticfleet_kafka_key_perms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticfleet-kafka.key
|
||||||
|
- mode: 640
|
||||||
|
- user: 947
|
||||||
|
- group: 939
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{{sls}}_state_not_allowed:
|
||||||
|
test.fail_without_changes:
|
||||||
|
- name: {{sls}}_state_not_allowed
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
@@ -14,7 +14,7 @@ if ! is_manager_node; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Get current list of Grid Node Agents that need to be upgraded
|
# Get current list of Grid Node Agents that need to be upgraded
|
||||||
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "http://localhost:5601/api/fleet/agents?perPage=20&page=1&kuery=NOT%20agent.version%20:%20%22{{ELASTICSEARCHDEFAULTS.elasticsearch.version}}%22%20and%20policy_id%20:%20%22so-grid-nodes_general%22&showInactive=false&getStatusSummary=true")
|
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "http://localhost:5601/api/fleet/agents?perPage=20&page=1&kuery=NOT%20agent.version%20:%20%22{{ELASTICSEARCHDEFAULTS.elasticsearch.version}}%22%20and%20policy_id%20:%20%22so-grid-nodes_general%22&showInactive=false&getStatusSummary=true" --retry 3 --retry-delay 30 --fail 2>/dev/null)
|
||||||
|
|
||||||
# Check to make sure that the server responded with good data - else, bail from script
|
# Check to make sure that the server responded with good data - else, bail from script
|
||||||
CHECKSUM=$(jq -r '.page' <<< "$RAW_JSON")
|
CHECKSUM=$(jq -r '.page' <<< "$RAW_JSON")
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ function update_es_urls() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Get current list of Fleet Elasticsearch URLs
|
# Get current list of Fleet Elasticsearch URLs
|
||||||
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_elasticsearch')
|
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_elasticsearch' --retry 3 --retry-delay 30 --fail 2>/dev/null)
|
||||||
|
|
||||||
# Check to make sure that the server responded with good data - else, bail from script
|
# Check to make sure that the server responded with good data - else, bail from script
|
||||||
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ if [[ -f $STATE_FILE_SUCCESS ]]; then
|
|||||||
latest_package_list=$(/usr/sbin/so-elastic-fleet-package-list)
|
latest_package_list=$(/usr/sbin/so-elastic-fleet-package-list)
|
||||||
echo '{ "packages" : []}' > $BULK_INSTALL_PACKAGE_LIST
|
echo '{ "packages" : []}' > $BULK_INSTALL_PACKAGE_LIST
|
||||||
rm -f $INSTALLED_PACKAGE_LIST
|
rm -f $INSTALLED_PACKAGE_LIST
|
||||||
echo $latest_package_list | jq '{packages: [.items[] | {name: .name, latest_version: .version, installed_version: .savedObject.attributes.install_version, subscription: .conditions.elastic.subscription }]}' >> $INSTALLED_PACKAGE_LIST
|
echo $latest_package_list | jq '{packages: [.items[] | {name: .name, latest_version: .version, installed_version: .installationInfo.version, subscription: .conditions.elastic.subscription }]}' >> $INSTALLED_PACKAGE_LIST
|
||||||
|
|
||||||
while read -r package; do
|
while read -r package; do
|
||||||
# get package details
|
# get package details
|
||||||
|
|||||||
@@ -3,11 +3,36 @@
|
|||||||
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
# 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; you may not use
|
# or more contributor license agreements. Licensed under the Elastic License 2.0; you may not use
|
||||||
# this file except in compliance with the Elastic License 2.0.
|
# this file except in compliance with the Elastic License 2.0.
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
{%- from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
{% from 'elasticfleet/map.jinja' import ELASTICFLEETMERGED %}
|
{%- from 'elasticfleet/map.jinja' import ELASTICFLEETMERGED %}
|
||||||
|
{%- from 'elasticfleet/config.map.jinja' import LOGSTASH_CONFIG_YAML %}
|
||||||
|
|
||||||
. /usr/sbin/so-common
|
. /usr/sbin/so-common
|
||||||
|
|
||||||
|
FORCE_UPDATE=false
|
||||||
|
UPDATE_CERTS=false
|
||||||
|
LOGSTASH_PILLAR_CONFIG_YAML="{{ LOGSTASH_CONFIG_YAML }}"
|
||||||
|
LOGSTASH_PILLAR_STATE_FILE="/opt/so/state/esfleet_logstash_config_pillar"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-f|--force)
|
||||||
|
FORCE_UPDATE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-c| --certs)
|
||||||
|
UPDATE_CERTS=true
|
||||||
|
FORCE_UPDATE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option $1"
|
||||||
|
echo "Usage: $0 [-f|--force] [-c|--certs]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# Only run on Managers
|
# Only run on Managers
|
||||||
if ! is_manager_node; then
|
if ! is_manager_node; then
|
||||||
printf "Not a Manager Node... Exiting"
|
printf "Not a Manager Node... Exiting"
|
||||||
@@ -17,17 +42,49 @@ fi
|
|||||||
function update_logstash_outputs() {
|
function update_logstash_outputs() {
|
||||||
if logstash_policy=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "http://localhost:5601/api/fleet/outputs/so-manager_logstash" --retry 3 --retry-delay 10 --fail 2>/dev/null); then
|
if logstash_policy=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "http://localhost:5601/api/fleet/outputs/so-manager_logstash" --retry 3 --retry-delay 10 --fail 2>/dev/null); then
|
||||||
SSL_CONFIG=$(echo "$logstash_policy" | jq -r '.item.ssl')
|
SSL_CONFIG=$(echo "$logstash_policy" | jq -r '.item.ssl')
|
||||||
|
LOGSTASHKEY=$(openssl rsa -in /etc/pki/elasticfleet-logstash.key)
|
||||||
|
LOGSTASHCRT=$(openssl x509 -in /etc/pki/elasticfleet-logstash.crt)
|
||||||
|
LOGSTASHCA=$(openssl x509 -in /etc/pki/tls/certs/intca.crt)
|
||||||
|
# Revert escaped \\n to \n for jq
|
||||||
|
LOGSTASH_PILLAR_CONFIG_YAML=$(printf '%b' "$LOGSTASH_PILLAR_CONFIG_YAML")
|
||||||
|
|
||||||
if SECRETS=$(echo "$logstash_policy" | jq -er '.item.secrets' 2>/dev/null); then
|
if SECRETS=$(echo "$logstash_policy" | jq -er '.item.secrets' 2>/dev/null); then
|
||||||
JSON_STRING=$(jq -n \
|
if [[ "$UPDATE_CERTS" != "true" ]]; then
|
||||||
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
# Reuse existing secret
|
||||||
--argjson SECRETS "$SECRETS" \
|
JSON_STRING=$(jq -n \
|
||||||
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
'{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":"","ssl": $SSL_CONFIG,"secrets": $SECRETS}')
|
--arg CONFIG_YAML "$LOGSTASH_PILLAR_CONFIG_YAML" \
|
||||||
|
--argjson SECRETS "$SECRETS" \
|
||||||
|
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
||||||
|
'{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":$CONFIG_YAML,"ssl": $SSL_CONFIG,"secrets": $SECRETS}')
|
||||||
|
else
|
||||||
|
# Update certs, creating new secret
|
||||||
|
JSON_STRING=$(jq -n \
|
||||||
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
|
--arg CONFIG_YAML "$LOGSTASH_PILLAR_CONFIG_YAML" \
|
||||||
|
--arg LOGSTASHKEY "$LOGSTASHKEY" \
|
||||||
|
--arg LOGSTASHCRT "$LOGSTASHCRT" \
|
||||||
|
--arg LOGSTASHCA "$LOGSTASHCA" \
|
||||||
|
'{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":$CONFIG_YAML,"ssl": {"certificate": $LOGSTASHCRT,"certificate_authorities":[ $LOGSTASHCA ]},"secrets": {"ssl":{"key": $LOGSTASHKEY }}}')
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
JSON_STRING=$(jq -n \
|
if [[ "$UPDATE_CERTS" != "true" ]]; then
|
||||||
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
# Reuse existing ssl config
|
||||||
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
JSON_STRING=$(jq -n \
|
||||||
'{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":"","ssl": $SSL_CONFIG}')
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
|
--arg CONFIG_YAML "$LOGSTASH_PILLAR_CONFIG_YAML" \
|
||||||
|
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
||||||
|
'{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":$CONFIG_YAML,"ssl": $SSL_CONFIG}')
|
||||||
|
else
|
||||||
|
# Update ssl config
|
||||||
|
JSON_STRING=$(jq -n \
|
||||||
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
|
--arg CONFIG_YAML "$LOGSTASH_PILLAR_CONFIG_YAML" \
|
||||||
|
--arg LOGSTASHKEY "$LOGSTASHKEY" \
|
||||||
|
--arg LOGSTASHCRT "$LOGSTASHCRT" \
|
||||||
|
--arg LOGSTASHCA "$LOGSTASHCA" \
|
||||||
|
'{"name":"grid-logstash","type":"logstash","hosts": $UPDATEDLIST,"is_default":true,"is_default_monitoring":true,"config_yaml":$CONFIG_YAML,"ssl": {"certificate": $LOGSTASHCRT,"key": $LOGSTASHKEY,"certificate_authorities":[ $LOGSTASHCA ]}}')
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -38,19 +95,42 @@ function update_kafka_outputs() {
|
|||||||
# Make sure SSL configuration is included in policy updates for Kafka output. SSL is configured in so-elastic-fleet-setup
|
# Make sure SSL configuration is included in policy updates for Kafka output. SSL is configured in so-elastic-fleet-setup
|
||||||
if kafka_policy=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "http://localhost:5601/api/fleet/outputs/so-manager_kafka" --fail 2>/dev/null); then
|
if kafka_policy=$(curl -K /opt/so/conf/elasticsearch/curl.config -L "http://localhost:5601/api/fleet/outputs/so-manager_kafka" --fail 2>/dev/null); then
|
||||||
SSL_CONFIG=$(echo "$kafka_policy" | jq -r '.item.ssl')
|
SSL_CONFIG=$(echo "$kafka_policy" | jq -r '.item.ssl')
|
||||||
|
KAFKAKEY=$(openssl rsa -in /etc/pki/elasticfleet-kafka.key)
|
||||||
|
KAFKACRT=$(openssl x509 -in /etc/pki/elasticfleet-kafka.crt)
|
||||||
|
KAFKACA=$(openssl x509 -in /etc/pki/tls/certs/intca.crt)
|
||||||
if SECRETS=$(echo "$kafka_policy" | jq -er '.item.secrets' 2>/dev/null); then
|
if SECRETS=$(echo "$kafka_policy" | jq -er '.item.secrets' 2>/dev/null); then
|
||||||
# Update policy when fleet has secrets enabled
|
if [[ "$UPDATE_CERTS" != "true" ]]; then
|
||||||
JSON_STRING=$(jq -n \
|
# Update policy when fleet has secrets enabled
|
||||||
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
JSON_STRING=$(jq -n \
|
||||||
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
--argjson SECRETS "$SECRETS" \
|
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
||||||
'{"name": "grid-kafka","type": "kafka","hosts": $UPDATEDLIST,"is_default": true,"is_default_monitoring": true,"config_yaml": "","ssl": $SSL_CONFIG,"secrets": $SECRETS}')
|
--argjson SECRETS "$SECRETS" \
|
||||||
|
'{"name": "grid-kafka","type": "kafka","hosts": $UPDATEDLIST,"is_default": true,"is_default_monitoring": true,"config_yaml": "","ssl": $SSL_CONFIG,"secrets": $SECRETS}')
|
||||||
|
else
|
||||||
|
# Update certs, creating new secret
|
||||||
|
JSON_STRING=$(jq -n \
|
||||||
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
|
--arg KAFKAKEY "$KAFKAKEY" \
|
||||||
|
--arg KAFKACRT "$KAFKACRT" \
|
||||||
|
--arg KAFKACA "$KAFKACA" \
|
||||||
|
'{"name": "grid-kafka","type": "kafka","hosts": $UPDATEDLIST,"is_default": true,"is_default_monitoring": true,"config_yaml": "","ssl": {"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"secrets": {"ssl":{"key": $KAFKAKEY }}}')
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Update policy when fleet has secrets disabled or policy hasn't been force updated
|
if [[ "$UPDATE_CERTS" != "true" ]]; then
|
||||||
JSON_STRING=$(jq -n \
|
# Update policy when fleet has secrets disabled or policy hasn't been force updated
|
||||||
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
JSON_STRING=$(jq -n \
|
||||||
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
'{"name": "grid-kafka","type": "kafka","hosts": $UPDATEDLIST,"is_default": true,"is_default_monitoring": true,"config_yaml": "","ssl": $SSL_CONFIG}')
|
--argjson SSL_CONFIG "$SSL_CONFIG" \
|
||||||
|
'{"name": "grid-kafka","type": "kafka","hosts": $UPDATEDLIST,"is_default": true,"is_default_monitoring": true,"config_yaml": "","ssl": $SSL_CONFIG}')
|
||||||
|
else
|
||||||
|
# Update ssl config
|
||||||
|
JSON_STRING=$(jq -n \
|
||||||
|
--arg UPDATEDLIST "$NEW_LIST_JSON" \
|
||||||
|
--arg KAFKAKEY "$KAFKAKEY" \
|
||||||
|
--arg KAFKACRT "$KAFKACRT" \
|
||||||
|
--arg KAFKACA "$KAFKACA" \
|
||||||
|
'{"name": "grid-kafka","type": "kafka","hosts": $UPDATEDLIST,"is_default": true,"is_default_monitoring": true,"config_yaml": "","ssl": { "certificate_authorities": [ $KAFKACA ], "certificate": $KAFKACRT, "key": $KAFKAKEY, "verification_mode": "full" }}')
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
# Update Kafka outputs
|
# Update Kafka outputs
|
||||||
curl -K /opt/so/conf/elasticsearch/curl.config -L -X PUT "localhost:5601/api/fleet/outputs/so-manager_kafka" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" | jq
|
curl -K /opt/so/conf/elasticsearch/curl.config -L -X PUT "localhost:5601/api/fleet/outputs/so-manager_kafka" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" | jq
|
||||||
@@ -62,7 +142,7 @@ function update_kafka_outputs() {
|
|||||||
|
|
||||||
{% if GLOBALS.pipeline == "KAFKA" %}
|
{% if GLOBALS.pipeline == "KAFKA" %}
|
||||||
# Get current list of Kafka Outputs
|
# Get current list of Kafka Outputs
|
||||||
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_kafka')
|
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_kafka' --retry 3 --retry-delay 30 --fail 2>/dev/null)
|
||||||
|
|
||||||
# Check to make sure that the server responded with good data - else, bail from script
|
# Check to make sure that the server responded with good data - else, bail from script
|
||||||
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
||||||
@@ -73,7 +153,7 @@ function update_kafka_outputs() {
|
|||||||
|
|
||||||
# Get the current list of kafka outputs & hash them
|
# Get the current list of kafka outputs & hash them
|
||||||
CURRENT_LIST=$(jq -c -r '.item.hosts' <<< "$RAW_JSON")
|
CURRENT_LIST=$(jq -c -r '.item.hosts' <<< "$RAW_JSON")
|
||||||
CURRENT_HASH=$(sha1sum <<< "$CURRENT_LIST" | awk '{print $1}')
|
CURRENT_HASH=$(sha256sum <<< "$CURRENT_LIST" | awk '{print $1}')
|
||||||
|
|
||||||
declare -a NEW_LIST=()
|
declare -a NEW_LIST=()
|
||||||
|
|
||||||
@@ -88,7 +168,7 @@ function update_kafka_outputs() {
|
|||||||
{# If global pipeline isn't set to KAFKA then assume default of REDIS / logstash #}
|
{# If global pipeline isn't set to KAFKA then assume default of REDIS / logstash #}
|
||||||
{% else %}
|
{% else %}
|
||||||
# Get current list of Logstash Outputs
|
# Get current list of Logstash Outputs
|
||||||
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_logstash')
|
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/outputs/so-manager_logstash' --retry 3 --retry-delay 30 --fail 2>/dev/null)
|
||||||
|
|
||||||
# Check to make sure that the server responded with good data - else, bail from script
|
# Check to make sure that the server responded with good data - else, bail from script
|
||||||
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
||||||
@@ -96,10 +176,19 @@ function update_kafka_outputs() {
|
|||||||
printf "Failed to query for current Logstash Outputs..."
|
printf "Failed to query for current Logstash Outputs..."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
# logstash adv config - compare pillar to last state file value
|
||||||
|
if [[ -f "$LOGSTASH_PILLAR_STATE_FILE" ]]; then
|
||||||
|
PREVIOUS_LOGSTASH_PILLAR_CONFIG_YAML=$(cat "$LOGSTASH_PILLAR_STATE_FILE")
|
||||||
|
if [[ "$LOGSTASH_PILLAR_CONFIG_YAML" != "$PREVIOUS_LOGSTASH_PILLAR_CONFIG_YAML" ]]; then
|
||||||
|
echo "Logstash pillar config has changed - forcing update"
|
||||||
|
FORCE_UPDATE=true
|
||||||
|
fi
|
||||||
|
echo "$LOGSTASH_PILLAR_CONFIG_YAML" > "$LOGSTASH_PILLAR_STATE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
# Get the current list of Logstash outputs & hash them
|
# Get the current list of Logstash outputs & hash them
|
||||||
CURRENT_LIST=$(jq -c -r '.item.hosts' <<< "$RAW_JSON")
|
CURRENT_LIST=$(jq -c -r '.item.hosts' <<< "$RAW_JSON")
|
||||||
CURRENT_HASH=$(sha1sum <<< "$CURRENT_LIST" | awk '{print $1}')
|
CURRENT_HASH=$(sha256sum <<< "$CURRENT_LIST" | awk '{print $1}')
|
||||||
|
|
||||||
declare -a NEW_LIST=()
|
declare -a NEW_LIST=()
|
||||||
|
|
||||||
@@ -148,10 +237,10 @@ function update_kafka_outputs() {
|
|||||||
|
|
||||||
# Sort & hash the new list of Logstash Outputs
|
# Sort & hash the new list of Logstash Outputs
|
||||||
NEW_LIST_JSON=$(jq --compact-output --null-input '$ARGS.positional' --args -- "${NEW_LIST[@]}")
|
NEW_LIST_JSON=$(jq --compact-output --null-input '$ARGS.positional' --args -- "${NEW_LIST[@]}")
|
||||||
NEW_HASH=$(sha1sum <<< "$NEW_LIST_JSON" | awk '{print $1}')
|
NEW_HASH=$(sha256sum <<< "$NEW_LIST_JSON" | awk '{print $1}')
|
||||||
|
|
||||||
# Compare the current & new list of outputs - if different, update the Logstash outputs
|
# Compare the current & new list of outputs - if different, update the Logstash outputs
|
||||||
if [ "$NEW_HASH" = "$CURRENT_HASH" ]; then
|
if [[ "$NEW_HASH" = "$CURRENT_HASH" ]] && [[ "$FORCE_UPDATE" != "true" ]]; then
|
||||||
printf "\nHashes match - no update needed.\n"
|
printf "\nHashes match - no update needed.\n"
|
||||||
printf "Current List: $CURRENT_LIST\nNew List: $NEW_LIST_JSON\n"
|
printf "Current List: $CURRENT_LIST\nNew List: $NEW_LIST_JSON\n"
|
||||||
|
|
||||||
|
|||||||
@@ -241,9 +241,11 @@ printf '%s\n'\
|
|||||||
"" >> "$global_pillar_file"
|
"" >> "$global_pillar_file"
|
||||||
|
|
||||||
# Call Elastic-Fleet Salt State
|
# Call Elastic-Fleet Salt State
|
||||||
|
printf "\nApplying elasticfleet state"
|
||||||
salt-call state.apply elasticfleet queue=True
|
salt-call state.apply elasticfleet queue=True
|
||||||
|
|
||||||
# Generate installers & install Elastic Agent on the node
|
# Generate installers & install Elastic Agent on the node
|
||||||
so-elastic-agent-gen-installers
|
so-elastic-agent-gen-installers
|
||||||
|
printf "\nApplying elasticfleet.install_agent_grid state"
|
||||||
salt-call state.apply elasticfleet.install_agent_grid queue=True
|
salt-call state.apply elasticfleet.install_agent_grid queue=True
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ function update_fleet_urls() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Get current list of Fleet Server URLs
|
# Get current list of Fleet Server URLs
|
||||||
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/fleet_server_hosts/grid-default')
|
RAW_JSON=$(curl -K /opt/so/conf/elasticsearch/curl.config 'http://localhost:5601/api/fleet/fleet_server_hosts/grid-default' --retry 3 --retry-delay 30 --fail 2>/dev/null)
|
||||||
|
|
||||||
# Check to make sure that the server responded with good data - else, bail from script
|
# Check to make sure that the server responded with good data - else, bail from script
|
||||||
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
CHECKSUM=$(jq -r '.item.id' <<< "$RAW_JSON")
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ if ! kafka_output=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L "http://l
|
|||||||
--arg KAFKACA "$KAFKACA" \
|
--arg KAFKACA "$KAFKACA" \
|
||||||
--arg MANAGER_IP "{{ GLOBALS.manager_ip }}:9092" \
|
--arg MANAGER_IP "{{ GLOBALS.manager_ip }}:9092" \
|
||||||
--arg KAFKA_OUTPUT_VERSION "$KAFKA_OUTPUT_VERSION" \
|
--arg KAFKA_OUTPUT_VERSION "$KAFKA_OUTPUT_VERSION" \
|
||||||
'{"name":"grid-kafka", "id":"so-manager_kafka","type":"kafka","hosts":[ $MANAGER_IP ],"is_default":false,"is_default_monitoring":false,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topics":[{"topic":"default-securityonion"}],"headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}'
|
'{"name":"grid-kafka", "id":"so-manager_kafka","type":"kafka","hosts":[ $MANAGER_IP ],"is_default":false,"is_default_monitoring":false,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topic":"default-securityonion","headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}'
|
||||||
)
|
)
|
||||||
if ! response=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L -X POST "localhost:5601/api/fleet/outputs" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" --fail 2>/dev/null); then
|
if ! response=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L -X POST "localhost:5601/api/fleet/outputs" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" --fail 2>/dev/null); then
|
||||||
echo -e "\nFailed to setup Elastic Fleet output policy for Kafka...\n"
|
echo -e "\nFailed to setup Elastic Fleet output policy for Kafka...\n"
|
||||||
@@ -67,7 +67,7 @@ elif kafka_output=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L "http://l
|
|||||||
--arg ENABLED_DISABLED "$ENABLED_DISABLED"\
|
--arg ENABLED_DISABLED "$ENABLED_DISABLED"\
|
||||||
--arg KAFKA_OUTPUT_VERSION "$KAFKA_OUTPUT_VERSION" \
|
--arg KAFKA_OUTPUT_VERSION "$KAFKA_OUTPUT_VERSION" \
|
||||||
--argjson HOSTS "$HOSTS" \
|
--argjson HOSTS "$HOSTS" \
|
||||||
'{"name":"grid-kafka","type":"kafka","hosts":$HOSTS,"is_default":$ENABLED_DISABLED,"is_default_monitoring":$ENABLED_DISABLED,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topics":[{"topic":"default-securityonion"}],"headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}'
|
'{"name":"grid-kafka","type":"kafka","hosts":$HOSTS,"is_default":$ENABLED_DISABLED,"is_default_monitoring":$ENABLED_DISABLED,"config_yaml":"","ssl":{"certificate_authorities":[ $KAFKACA ],"certificate": $KAFKACRT ,"key":"","verification_mode":"full"},"proxy_id":null,"client_id":"Elastic","version": $KAFKA_OUTPUT_VERSION ,"compression":"none","auth_type":"ssl","partition":"round_robin","round_robin":{"group_events":10},"topic":"default-securityonion","headers":[{"key":"","value":""}],"timeout":30,"broker_timeout":30,"required_acks":1,"secrets":{"ssl":{"key": $KAFKAKEY }}}'
|
||||||
)
|
)
|
||||||
if ! response=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L -X PUT "localhost:5601/api/fleet/outputs/so-manager_kafka" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" --fail 2>/dev/null); then
|
if ! response=$(curl -sK /opt/so/conf/elasticsearch/curl.config -L -X PUT "localhost:5601/api/fleet/outputs/so-manager_kafka" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d "$JSON_STRING" --fail 2>/dev/null); then
|
||||||
echo -e "\nFailed to force update to Elastic Fleet output policy for Kafka...\n"
|
echo -e "\nFailed to force update to Elastic Fleet output policy for Kafka...\n"
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ catrustscript:
|
|||||||
GLOBALS: {{ GLOBALS }}
|
GLOBALS: {{ GLOBALS }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
cacertz:
|
elasticsearch_cacerts:
|
||||||
file.managed:
|
file.managed:
|
||||||
- name: /opt/so/conf/ca/cacerts
|
- name: /opt/so/conf/ca/cacerts
|
||||||
- source: salt://elasticsearch/cacerts
|
- source: salt://elasticsearch/cacerts
|
||||||
- user: 939
|
- user: 939
|
||||||
- group: 939
|
- group: 939
|
||||||
|
|
||||||
capemz:
|
elasticsearch_capems:
|
||||||
file.managed:
|
file.managed:
|
||||||
- name: /opt/so/conf/ca/tls-ca-bundle.pem
|
- name: /opt/so/conf/ca/tls-ca-bundle.pem
|
||||||
- source: salt://elasticsearch/tls-ca-bundle.pem
|
- source: salt://elasticsearch/tls-ca-bundle.pem
|
||||||
|
|||||||
@@ -5,11 +5,6 @@
|
|||||||
|
|
||||||
{% from 'allowed_states.map.jinja' import allowed_states %}
|
{% from 'allowed_states.map.jinja' import allowed_states %}
|
||||||
{% if sls.split('.')[0] in allowed_states %}
|
{% if sls.split('.')[0] in allowed_states %}
|
||||||
|
|
||||||
include:
|
|
||||||
- ssl
|
|
||||||
- elasticsearch.ca
|
|
||||||
|
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
||||||
{% from 'elasticsearch/config.map.jinja' import ELASTICSEARCHMERGED %}
|
{% from 'elasticsearch/config.map.jinja' import ELASTICSEARCHMERGED %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
elasticsearch:
|
elasticsearch:
|
||||||
enabled: false
|
enabled: false
|
||||||
version: 8.18.8
|
version: 9.0.8
|
||||||
index_clean: true
|
index_clean: true
|
||||||
config:
|
config:
|
||||||
action:
|
action:
|
||||||
@@ -72,6 +72,8 @@ elasticsearch:
|
|||||||
actions:
|
actions:
|
||||||
set_priority:
|
set_priority:
|
||||||
priority: 0
|
priority: 0
|
||||||
|
allocate:
|
||||||
|
number_of_replicas: ""
|
||||||
min_age: 60d
|
min_age: 60d
|
||||||
delete:
|
delete:
|
||||||
actions:
|
actions:
|
||||||
@@ -84,11 +86,25 @@ elasticsearch:
|
|||||||
max_primary_shard_size: 50gb
|
max_primary_shard_size: 50gb
|
||||||
set_priority:
|
set_priority:
|
||||||
priority: 100
|
priority: 100
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments: ""
|
||||||
|
shrink:
|
||||||
|
max_primary_shard_size: ""
|
||||||
|
method: COUNT
|
||||||
|
number_of_shards: ""
|
||||||
min_age: 0ms
|
min_age: 0ms
|
||||||
warm:
|
warm:
|
||||||
actions:
|
actions:
|
||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments: ""
|
||||||
|
shrink:
|
||||||
|
max_primary_shard_size: ""
|
||||||
|
method: COUNT
|
||||||
|
number_of_shards: ""
|
||||||
|
allocate:
|
||||||
|
number_of_replicas: ""
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
so-case:
|
so-case:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
@@ -245,7 +261,6 @@ elasticsearch:
|
|||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
warm: 7
|
|
||||||
so-detection:
|
so-detection:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
index_template:
|
index_template:
|
||||||
@@ -284,6 +299,19 @@ elasticsearch:
|
|||||||
hot:
|
hot:
|
||||||
actions: {}
|
actions: {}
|
||||||
min_age: 0ms
|
min_age: 0ms
|
||||||
|
sos-backup:
|
||||||
|
index_sorting: false
|
||||||
|
index_template:
|
||||||
|
composed_of: []
|
||||||
|
ignore_missing_component_templates: []
|
||||||
|
index_patterns:
|
||||||
|
- sos-backup-*
|
||||||
|
priority: 501
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
index:
|
||||||
|
number_of_replicas: 0
|
||||||
|
number_of_shards: 1
|
||||||
so-assistant-chat:
|
so-assistant-chat:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
index_template:
|
index_template:
|
||||||
@@ -584,7 +612,6 @@ elasticsearch:
|
|||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
warm: 7
|
|
||||||
so-import:
|
so-import:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
index_template:
|
index_template:
|
||||||
@@ -830,53 +857,11 @@ elasticsearch:
|
|||||||
composed_of:
|
composed_of:
|
||||||
- agent-mappings
|
- agent-mappings
|
||||||
- dtc-agent-mappings
|
- dtc-agent-mappings
|
||||||
- base-mappings
|
|
||||||
- dtc-base-mappings
|
|
||||||
- client-mappings
|
|
||||||
- dtc-client-mappings
|
|
||||||
- container-mappings
|
|
||||||
- destination-mappings
|
|
||||||
- dtc-destination-mappings
|
|
||||||
- pb-override-destination-mappings
|
|
||||||
- dll-mappings
|
|
||||||
- dns-mappings
|
|
||||||
- dtc-dns-mappings
|
|
||||||
- ecs-mappings
|
|
||||||
- dtc-ecs-mappings
|
|
||||||
- error-mappings
|
|
||||||
- event-mappings
|
|
||||||
- dtc-event-mappings
|
|
||||||
- file-mappings
|
|
||||||
- dtc-file-mappings
|
|
||||||
- group-mappings
|
|
||||||
- host-mappings
|
- host-mappings
|
||||||
- dtc-host-mappings
|
- dtc-host-mappings
|
||||||
- http-mappings
|
- http-mappings
|
||||||
- dtc-http-mappings
|
- dtc-http-mappings
|
||||||
- log-mappings
|
|
||||||
- metadata-mappings
|
- metadata-mappings
|
||||||
- network-mappings
|
|
||||||
- dtc-network-mappings
|
|
||||||
- observer-mappings
|
|
||||||
- dtc-observer-mappings
|
|
||||||
- organization-mappings
|
|
||||||
- package-mappings
|
|
||||||
- process-mappings
|
|
||||||
- dtc-process-mappings
|
|
||||||
- related-mappings
|
|
||||||
- rule-mappings
|
|
||||||
- dtc-rule-mappings
|
|
||||||
- server-mappings
|
|
||||||
- service-mappings
|
|
||||||
- dtc-service-mappings
|
|
||||||
- source-mappings
|
|
||||||
- dtc-source-mappings
|
|
||||||
- pb-override-source-mappings
|
|
||||||
- threat-mappings
|
|
||||||
- tls-mappings
|
|
||||||
- url-mappings
|
|
||||||
- user_agent-mappings
|
|
||||||
- dtc-user_agent-mappings
|
|
||||||
- common-settings
|
- common-settings
|
||||||
- common-dynamic-mappings
|
- common-dynamic-mappings
|
||||||
data_stream:
|
data_stream:
|
||||||
@@ -932,7 +917,6 @@ elasticsearch:
|
|||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
warm: 7
|
|
||||||
so-hydra:
|
so-hydra:
|
||||||
close: 30
|
close: 30
|
||||||
delete: 365
|
delete: 365
|
||||||
@@ -1043,7 +1027,6 @@ elasticsearch:
|
|||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
warm: 7
|
|
||||||
so-lists:
|
so-lists:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
index_template:
|
index_template:
|
||||||
@@ -1127,6 +1110,8 @@ elasticsearch:
|
|||||||
actions:
|
actions:
|
||||||
set_priority:
|
set_priority:
|
||||||
priority: 0
|
priority: 0
|
||||||
|
allocate:
|
||||||
|
number_of_replicas: ""
|
||||||
min_age: 60d
|
min_age: 60d
|
||||||
delete:
|
delete:
|
||||||
actions:
|
actions:
|
||||||
@@ -1139,11 +1124,25 @@ elasticsearch:
|
|||||||
max_primary_shard_size: 50gb
|
max_primary_shard_size: 50gb
|
||||||
set_priority:
|
set_priority:
|
||||||
priority: 100
|
priority: 100
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments: ""
|
||||||
|
shrink:
|
||||||
|
max_primary_shard_size: ""
|
||||||
|
method: COUNT
|
||||||
|
number_of_shards: ""
|
||||||
min_age: 0ms
|
min_age: 0ms
|
||||||
warm:
|
warm:
|
||||||
actions:
|
actions:
|
||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
|
allocate:
|
||||||
|
number_of_replicas: ""
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments: ""
|
||||||
|
shrink:
|
||||||
|
max_primary_shard_size: ""
|
||||||
|
method: COUNT
|
||||||
|
number_of_shards: ""
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
so-logs-detections_x_alerts:
|
so-logs-detections_x_alerts:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
@@ -3123,7 +3122,6 @@ elasticsearch:
|
|||||||
set_priority:
|
set_priority:
|
||||||
priority: 50
|
priority: 50
|
||||||
min_age: 30d
|
min_age: 30d
|
||||||
warm: 7
|
|
||||||
so-logs-system_x_application:
|
so-logs-system_x_application:
|
||||||
index_sorting: false
|
index_sorting: false
|
||||||
index_template:
|
index_template:
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
{% from 'elasticsearch/template.map.jinja' import ES_INDEX_SETTINGS %}
|
{% from 'elasticsearch/template.map.jinja' import ES_INDEX_SETTINGS %}
|
||||||
|
|
||||||
include:
|
include:
|
||||||
|
- ca
|
||||||
|
- elasticsearch.ca
|
||||||
|
- elasticsearch.ssl
|
||||||
- elasticsearch.config
|
- elasticsearch.config
|
||||||
- elasticsearch.sostatus
|
- elasticsearch.sostatus
|
||||||
|
|
||||||
@@ -61,11 +64,7 @@ so-elasticsearch:
|
|||||||
- /nsm/elasticsearch:/usr/share/elasticsearch/data:rw
|
- /nsm/elasticsearch:/usr/share/elasticsearch/data:rw
|
||||||
- /opt/so/log/elasticsearch:/var/log/elasticsearch:rw
|
- /opt/so/log/elasticsearch:/var/log/elasticsearch:rw
|
||||||
- /opt/so/conf/ca/cacerts:/usr/share/elasticsearch/jdk/lib/security/cacerts:ro
|
- /opt/so/conf/ca/cacerts:/usr/share/elasticsearch/jdk/lib/security/cacerts:ro
|
||||||
{% if GLOBALS.is_manager %}
|
|
||||||
- /etc/pki/ca.crt:/usr/share/elasticsearch/config/ca.crt:ro
|
|
||||||
{% else %}
|
|
||||||
- /etc/pki/tls/certs/intca.crt:/usr/share/elasticsearch/config/ca.crt:ro
|
- /etc/pki/tls/certs/intca.crt:/usr/share/elasticsearch/config/ca.crt:ro
|
||||||
{% endif %}
|
|
||||||
- /etc/pki/elasticsearch.crt:/usr/share/elasticsearch/config/elasticsearch.crt:ro
|
- /etc/pki/elasticsearch.crt:/usr/share/elasticsearch/config/elasticsearch.crt:ro
|
||||||
- /etc/pki/elasticsearch.key:/usr/share/elasticsearch/config/elasticsearch.key:ro
|
- /etc/pki/elasticsearch.key:/usr/share/elasticsearch/config/elasticsearch.key:ro
|
||||||
- /etc/pki/elasticsearch.p12:/usr/share/elasticsearch/config/elasticsearch.p12:ro
|
- /etc/pki/elasticsearch.p12:/usr/share/elasticsearch/config/elasticsearch.p12:ro
|
||||||
@@ -82,22 +81,21 @@ so-elasticsearch:
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
- watch:
|
- watch:
|
||||||
- file: cacertz
|
- file: trusttheca
|
||||||
|
- x509: elasticsearch_crt
|
||||||
|
- x509: elasticsearch_key
|
||||||
|
- file: elasticsearch_cacerts
|
||||||
- file: esyml
|
- file: esyml
|
||||||
- require:
|
- require:
|
||||||
|
- file: trusttheca
|
||||||
|
- x509: elasticsearch_crt
|
||||||
|
- x509: elasticsearch_key
|
||||||
|
- file: elasticsearch_cacerts
|
||||||
- file: esyml
|
- file: esyml
|
||||||
- file: eslog4jfile
|
- file: eslog4jfile
|
||||||
- file: nsmesdir
|
- file: nsmesdir
|
||||||
- file: eslogdir
|
- file: eslogdir
|
||||||
- file: cacertz
|
|
||||||
- x509: /etc/pki/elasticsearch.crt
|
|
||||||
- x509: /etc/pki/elasticsearch.key
|
|
||||||
- file: elasticp12perms
|
- file: elasticp12perms
|
||||||
{% if GLOBALS.is_manager %}
|
|
||||||
- x509: pki_public_ca_crt
|
|
||||||
{% else %}
|
|
||||||
- x509: trusttheca
|
|
||||||
{% endif %}
|
|
||||||
- cmd: auth_users_roles_inode
|
- cmd: auth_users_roles_inode
|
||||||
- cmd: auth_users_inode
|
- cmd: auth_users_inode
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,90 @@
|
|||||||
{
|
{
|
||||||
"description" : "kratos",
|
"description": "kratos",
|
||||||
"processors" : [
|
"processors": [
|
||||||
{"set":{"field":"audience","value":"access","override":false,"ignore_failure":true}},
|
{
|
||||||
{"set":{"field":"event.dataset","ignore_empty_value":true,"ignore_failure":true,"value":"kratos.{{{audience}}}","media_type":"text/plain"}},
|
"set": {
|
||||||
{"set":{"field":"event.action","ignore_failure":true,"copy_from":"msg" }},
|
"field": "audience",
|
||||||
{ "pipeline": { "name": "common" } }
|
"value": "access",
|
||||||
]
|
"override": false,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "event.dataset",
|
||||||
|
"ignore_empty_value": true,
|
||||||
|
"ignore_failure": true,
|
||||||
|
"value": "kratos.{{{audience}}}",
|
||||||
|
"media_type": "text/plain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "event.action",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"copy_from": "msg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http_request",
|
||||||
|
"target_field": "http.request",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http_response",
|
||||||
|
"target_field": "http.response",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http.request.path",
|
||||||
|
"target_field": "http.uri",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http.request.method",
|
||||||
|
"target_field": "http.method",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http.request.method",
|
||||||
|
"target_field": "http.method",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http.request.query",
|
||||||
|
"target_field": "http.query",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "http.request.headers.user-agent",
|
||||||
|
"target_field": "http.useragent",
|
||||||
|
"ignore_failure": true,
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "common"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,79 @@
|
|||||||
{
|
{
|
||||||
"description" : "suricata.alert",
|
"description": "suricata.alert",
|
||||||
"processors" : [
|
"processors": [
|
||||||
{ "set": { "if": "ctx.event?.imported != true", "field": "_index", "value": "logs-suricata.alerts-so" } },
|
{
|
||||||
{ "set": { "field": "tags","value": "alert" }},
|
"set": {
|
||||||
{ "rename":{ "field": "message2.alert", "target_field": "rule", "ignore_failure": true } },
|
"if": "ctx.event?.imported != true",
|
||||||
{ "rename":{ "field": "rule.signature", "target_field": "rule.name", "ignore_failure": true } },
|
"field": "_index",
|
||||||
{ "rename":{ "field": "rule.ref", "target_field": "rule.version", "ignore_failure": true } },
|
"value": "logs-suricata.alerts-so"
|
||||||
{ "rename":{ "field": "rule.signature_id", "target_field": "rule.uuid", "ignore_failure": true } },
|
}
|
||||||
{ "rename":{ "field": "rule.signature_id", "target_field": "rule.signature", "ignore_failure": true } },
|
},
|
||||||
{ "rename":{ "field": "message2.payload_printable", "target_field": "network.data.decoded", "ignore_failure": true } },
|
{
|
||||||
{ "dissect": { "field": "rule.rule", "pattern": "%{?prefix}content:\"%{dns.query_name}\"%{?remainder}", "ignore_missing": true, "ignore_failure": true } },
|
"set": {
|
||||||
{ "pipeline": { "name": "common.nids" } }
|
"field": "tags",
|
||||||
]
|
"value": "alert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.alert",
|
||||||
|
"target_field": "rule",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "rule.signature",
|
||||||
|
"target_field": "rule.name",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "rule.ref",
|
||||||
|
"target_field": "rule.version",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "rule.signature_id",
|
||||||
|
"target_field": "rule.uuid",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "rule.signature_id",
|
||||||
|
"target_field": "rule.signature",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.payload_printable",
|
||||||
|
"target_field": "network.data.decoded",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dissect": {
|
||||||
|
"field": "rule.rule",
|
||||||
|
"pattern": "%{?prefix}content:\"%{dns.query_name}\"%{?remainder}",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "common.nids"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,155 @@
|
|||||||
{
|
{
|
||||||
"description" : "suricata.common",
|
"description": "suricata.common",
|
||||||
"processors" : [
|
"processors": [
|
||||||
{ "json": { "field": "message", "target_field": "message2", "ignore_failure": true } },
|
{
|
||||||
{ "rename": { "field": "message2.pkt_src", "target_field": "network.packet_source","ignore_failure": true } },
|
"json": {
|
||||||
{ "rename": { "field": "message2.proto", "target_field": "network.transport", "ignore_failure": true } },
|
"field": "message",
|
||||||
{ "rename": { "field": "message2.in_iface", "target_field": "observer.ingress.interface.name", "ignore_failure": true } },
|
"target_field": "message2",
|
||||||
{ "rename": { "field": "message2.flow_id", "target_field": "log.id.uid", "ignore_failure": true } },
|
"ignore_failure": true
|
||||||
{ "rename": { "field": "message2.src_ip", "target_field": "source.ip", "ignore_failure": true } },
|
}
|
||||||
{ "rename": { "field": "message2.src_port", "target_field": "source.port", "ignore_failure": true } },
|
},
|
||||||
{ "rename": { "field": "message2.dest_ip", "target_field": "destination.ip", "ignore_failure": true } },
|
{
|
||||||
{ "rename": { "field": "message2.dest_port", "target_field": "destination.port", "ignore_failure": true } },
|
"rename": {
|
||||||
{ "rename": { "field": "message2.vlan", "target_field": "network.vlan.id", "ignore_failure": true } },
|
"field": "message2.pkt_src",
|
||||||
{ "rename": { "field": "message2.community_id", "target_field": "network.community_id", "ignore_missing": true } },
|
"target_field": "network.packet_source",
|
||||||
{ "rename": { "field": "message2.xff", "target_field": "xff.ip", "ignore_missing": true } },
|
"ignore_failure": true
|
||||||
{ "set": { "field": "event.dataset", "value": "{{ message2.event_type }}" } },
|
}
|
||||||
{ "set": { "field": "observer.name", "value": "{{agent.name}}" } },
|
},
|
||||||
{ "set": { "field": "event.ingested", "value": "{{@timestamp}}" } },
|
{
|
||||||
{ "date": { "field": "message2.timestamp", "target_field": "@timestamp", "formats": ["ISO8601", "UNIX"], "timezone": "UTC", "ignore_failure": true } },
|
"rename": {
|
||||||
{ "remove":{ "field": "agent", "ignore_failure": true } },
|
"field": "message2.proto",
|
||||||
{"append":{"field":"related.ip","value":["{{source.ip}}","{{destination.ip}}"],"allow_duplicates":false,"ignore_failure":true}},
|
"target_field": "network.transport",
|
||||||
{
|
"ignore_failure": true
|
||||||
"script": {
|
}
|
||||||
"source": "boolean isPrivate(def ip) { if (ip == null) return false; int dot1 = ip.indexOf('.'); if (dot1 == -1) return false; int dot2 = ip.indexOf('.', dot1 + 1); if (dot2 == -1) return false; int first = Integer.parseInt(ip.substring(0, dot1)); if (first == 10) return true; if (first == 192 && ip.startsWith('168.', dot1 + 1)) return true; if (first == 172) { int second = Integer.parseInt(ip.substring(dot1 + 1, dot2)); return second >= 16 && second <= 31; } return false; } String[] fields = new String[] {\"source\", \"destination\"}; for (int i = 0; i < fields.length; i++) { def field = fields[i]; def ip = ctx[field]?.ip; if (ip != null) { if (ctx.network == null) ctx.network = new HashMap(); if (isPrivate(ip)) { if (ctx.network.private_ip == null) ctx.network.private_ip = new ArrayList(); if (!ctx.network.private_ip.contains(ip)) ctx.network.private_ip.add(ip); } else { if (ctx.network.public_ip == null) ctx.network.public_ip = new ArrayList(); if (!ctx.network.public_ip.contains(ip)) ctx.network.public_ip.add(ip); } } }",
|
},
|
||||||
"ignore_failure": false
|
{
|
||||||
}
|
"rename": {
|
||||||
},
|
"field": "message2.in_iface",
|
||||||
{ "pipeline": { "if": "ctx?.event?.dataset != null", "name": "suricata.{{event.dataset}}" } }
|
"target_field": "observer.ingress.interface.name",
|
||||||
]
|
"ignore_failure": true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.flow_id",
|
||||||
|
"target_field": "log.id.uid",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.src_ip",
|
||||||
|
"target_field": "source.ip",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.src_port",
|
||||||
|
"target_field": "source.port",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dest_ip",
|
||||||
|
"target_field": "destination.ip",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dest_port",
|
||||||
|
"target_field": "destination.port",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.vlan",
|
||||||
|
"target_field": "network.vlan.id",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.community_id",
|
||||||
|
"target_field": "network.community_id",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.xff",
|
||||||
|
"target_field": "xff.ip",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "event.dataset",
|
||||||
|
"value": "{{ message2.event_type }}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "observer.name",
|
||||||
|
"value": "{{agent.name}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "event.ingested",
|
||||||
|
"value": "{{@timestamp}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": {
|
||||||
|
"field": "message2.timestamp",
|
||||||
|
"target_field": "@timestamp",
|
||||||
|
"formats": [
|
||||||
|
"ISO8601",
|
||||||
|
"UNIX"
|
||||||
|
],
|
||||||
|
"timezone": "UTC",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"remove": {
|
||||||
|
"field": "agent",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"append": {
|
||||||
|
"field": "related.ip",
|
||||||
|
"value": [
|
||||||
|
"{{source.ip}}",
|
||||||
|
"{{destination.ip}}"
|
||||||
|
],
|
||||||
|
"allow_duplicates": false,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "boolean isPrivate(def ip) { if (ip == null) return false; int dot1 = ip.indexOf('.'); if (dot1 == -1) return false; int dot2 = ip.indexOf('.', dot1 + 1); if (dot2 == -1) return false; int first = Integer.parseInt(ip.substring(0, dot1)); if (first == 10) return true; if (first == 192 && ip.startsWith('168.', dot1 + 1)) return true; if (first == 172) { int second = Integer.parseInt(ip.substring(dot1 + 1, dot2)); return second >= 16 && second <= 31; } return false; } String[] fields = new String[] {\"source\", \"destination\"}; for (int i = 0; i < fields.length; i++) { def field = fields[i]; def ip = ctx[field]?.ip; if (ip != null) { if (ctx.network == null) ctx.network = new HashMap(); if (isPrivate(ip)) { if (ctx.network.private_ip == null) ctx.network.private_ip = new ArrayList(); if (!ctx.network.private_ip.contains(ip)) ctx.network.private_ip.add(ip); } else { if (ctx.network.public_ip == null) ctx.network.public_ip = new ArrayList(); if (!ctx.network.public_ip.contains(ip)) ctx.network.public_ip.add(ip); } } }",
|
||||||
|
"ignore_failure": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.capture_file",
|
||||||
|
"target_field": "suricata.capture_file",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"if": "ctx?.event?.dataset != null",
|
||||||
|
"name": "suricata.{{event.dataset}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,21 +1,136 @@
|
|||||||
{
|
{
|
||||||
"description" : "suricata.dns",
|
"description": "suricata.dns",
|
||||||
"processors" : [
|
"processors": [
|
||||||
{ "rename": { "field": "message2.proto", "target_field": "network.transport", "ignore_missing": true } },
|
{
|
||||||
{ "rename": { "field": "message2.app_proto", "target_field": "network.protocol", "ignore_missing": true } },
|
"rename": {
|
||||||
{ "rename": { "field": "message2.dns.type", "target_field": "dns.query.type", "ignore_missing": true } },
|
"field": "message2.proto",
|
||||||
{ "rename": { "field": "message2.dns.tx_id", "target_field": "dns.id", "ignore_missing": true } },
|
"target_field": "network.transport",
|
||||||
{ "rename": { "field": "message2.dns.version", "target_field": "dns.version", "ignore_missing": true } },
|
"ignore_missing": true
|
||||||
{ "rename": { "field": "message2.dns.rrname", "target_field": "dns.query.name", "ignore_missing": true } },
|
}
|
||||||
{ "rename": { "field": "message2.dns.rrtype", "target_field": "dns.query.type_name", "ignore_missing": true } },
|
},
|
||||||
{ "rename": { "field": "message2.dns.flags", "target_field": "dns.flags", "ignore_missing": true } },
|
{
|
||||||
{ "rename": { "field": "message2.dns.qr", "target_field": "dns.qr", "ignore_missing": true } },
|
"rename": {
|
||||||
{ "rename": { "field": "message2.dns.rd", "target_field": "dns.recursion.desired", "ignore_missing": true } },
|
"field": "message2.app_proto",
|
||||||
{ "rename": { "field": "message2.dns.ra", "target_field": "dns.recursion.available", "ignore_missing": true } },
|
"target_field": "network.protocol",
|
||||||
{ "rename": { "field": "message2.dns.rcode", "target_field": "dns.response.code_name", "ignore_missing": true } },
|
"ignore_missing": true
|
||||||
{ "rename": { "field": "message2.dns.grouped.A", "target_field": "dns.answers.data", "ignore_missing": true } },
|
}
|
||||||
{ "rename": { "field": "message2.dns.grouped.CNAME", "target_field": "dns.answers.name", "ignore_missing": true } },
|
},
|
||||||
{ "pipeline": { "if": "ctx.dns.query?.name != null && ctx.dns.query.name.contains('.')", "name": "dns.tld" } },
|
{
|
||||||
{ "pipeline": { "name": "common" } }
|
"rename": {
|
||||||
]
|
"field": "message2.dns.type",
|
||||||
}
|
"target_field": "dns.query.type",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.tx_id",
|
||||||
|
"target_field": "dns.tx_id",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.id",
|
||||||
|
"target_field": "dns.id",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.version",
|
||||||
|
"target_field": "dns.version",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "suricata.dnsv3",
|
||||||
|
"ignore_missing_pipeline": true,
|
||||||
|
"if": "ctx?.dns?.version != null && ctx?.dns?.version == 3",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.rrname",
|
||||||
|
"target_field": "dns.query.name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.rrtype",
|
||||||
|
"target_field": "dns.query.type_name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.flags",
|
||||||
|
"target_field": "dns.flags",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.qr",
|
||||||
|
"target_field": "dns.qr",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.rd",
|
||||||
|
"target_field": "dns.recursion.desired",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.ra",
|
||||||
|
"target_field": "dns.recursion.available",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.opcode",
|
||||||
|
"target_field": "dns.opcode",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.rcode",
|
||||||
|
"target_field": "dns.response.code_name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.grouped.A",
|
||||||
|
"target_field": "dns.answers.data",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.grouped.CNAME",
|
||||||
|
"target_field": "dns.answers.name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"if": "ctx.dns.query?.name != null && ctx.dns.query.name.contains('.')",
|
||||||
|
"name": "dns.tld"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "common"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
56
salt/elasticsearch/files/ingest/suricata.dnsv3
Normal file
56
salt/elasticsearch/files/ingest/suricata.dnsv3
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"processors": [
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.dns.queries",
|
||||||
|
"target_field": "dns.queries",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx?.dns?.queries != null && ctx?.dns?.queries.length > 0) {\n if (ctx.dns == null) {\n ctx.dns = new HashMap();\n }\n if (ctx.dns.query == null) {\n ctx.dns.query = new HashMap();\n }\n ctx.dns.query.name = ctx?.dns?.queries[0].rrname;\n}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx?.dns?.queries != null && ctx?.dns?.queries.length > 0) {\n if (ctx.dns == null) {\n ctx.dns = new HashMap();\n }\n if (ctx.dns.query == null) {\n ctx.dns.query = new HashMap();\n }\n ctx.dns.query.type_name = ctx?.dns?.queries[0].rrtype;\n}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"foreach": {
|
||||||
|
"field": "dns.queries",
|
||||||
|
"processor": {
|
||||||
|
"rename": {
|
||||||
|
"field": "_ingest._value.rrname",
|
||||||
|
"target_field": "_ingest._value.name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"foreach": {
|
||||||
|
"field": "dns.queries",
|
||||||
|
"processor": {
|
||||||
|
"rename": {
|
||||||
|
"field": "_ingest._value.rrtype",
|
||||||
|
"target_field": "_ingest._value.type_name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "suricata.tld",
|
||||||
|
"ignore_missing_pipeline": true,
|
||||||
|
"if": "ctx?.dns?.queries != null && ctx?.dns?.queries.length > 0",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
52
salt/elasticsearch/files/ingest/suricata.tld
Normal file
52
salt/elasticsearch/files/ingest/suricata.tld
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"processors": [
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.name != null && q.name.contains('.')) {\n q.top_level_domain = q.name.substring(q.name.lastIndexOf('.') + 1);\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.name != null && q.name.contains('.')) {\n q.query_without_tld = q.name.substring(0, q.name.lastIndexOf('.'));\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.query_without_tld != null && q.query_without_tld.contains('.')) {\n q.parent_domain = q.query_without_tld.substring(q.query_without_tld.lastIndexOf('.') + 1);\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.query_without_tld != null && q.query_without_tld.contains('.')) {\n q.subdomain = q.query_without_tld.substring(0, q.query_without_tld.lastIndexOf('.'));\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.parent_domain != null && q.top_level_domain != null) {\n q.highest_registered_domain = q.parent_domain + \".\" + q.top_level_domain;\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.subdomain != null) {\n q.subdomain_length = q.subdomain.length();\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n if (q.parent_domain != null) {\n q.parent_domain_length = q.parent_domain.length();\n }\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns != null && ctx.dns.queries != null) {\n for (def q : ctx.dns.queries) {\n q.remove('query_without_tld');\n }\n}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
61
salt/elasticsearch/files/ingest/zeek.analyzer
Normal file
61
salt/elasticsearch/files/ingest/zeek.analyzer
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"description": "zeek.analyzer",
|
||||||
|
"processors": [
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "event.dataset",
|
||||||
|
"value": "analyzer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"remove": {
|
||||||
|
"field": [
|
||||||
|
"host"
|
||||||
|
],
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"field": "message",
|
||||||
|
"target_field": "message2",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "network.protocol",
|
||||||
|
"copy_from": "message2.analyzer_name",
|
||||||
|
"ignore_empty_value": true,
|
||||||
|
"if": "ctx?.message2?.analyzer_kind == 'protocol'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"field": "network.protocol",
|
||||||
|
"ignore_empty_value": true,
|
||||||
|
"if": "ctx?.message2?.analyzer_kind != 'protocol'",
|
||||||
|
"copy_from": "message2.proto"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lowercase": {
|
||||||
|
"field": "network.protocol",
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.failure_reason",
|
||||||
|
"target_field": "error.reason",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "zeek.common"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,35 +1,227 @@
|
|||||||
{
|
{
|
||||||
"description" : "zeek.dns",
|
"description": "zeek.dns",
|
||||||
"processors" : [
|
"processors": [
|
||||||
{ "set": { "field": "event.dataset", "value": "dns" } },
|
{
|
||||||
{ "remove": { "field": ["host"], "ignore_failure": true } },
|
"set": {
|
||||||
{ "json": { "field": "message", "target_field": "message2", "ignore_failure": true } },
|
"field": "event.dataset",
|
||||||
{ "dot_expander": { "field": "id.orig_h", "path": "message2", "ignore_failure": true } },
|
"value": "dns"
|
||||||
{ "rename": { "field": "message2.proto", "target_field": "network.transport", "ignore_missing": true } },
|
}
|
||||||
{ "rename": { "field": "message2.trans_id", "target_field": "dns.id", "ignore_missing": true } },
|
},
|
||||||
{ "rename": { "field": "message2.rtt", "target_field": "event.duration", "ignore_missing": true } },
|
{
|
||||||
{ "rename": { "field": "message2.query", "target_field": "dns.query.name", "ignore_missing": true } },
|
"remove": {
|
||||||
{ "rename": { "field": "message2.qclass", "target_field": "dns.query.class", "ignore_missing": true } },
|
"field": [
|
||||||
{ "rename": { "field": "message2.qclass_name", "target_field": "dns.query.class_name", "ignore_missing": true } },
|
"host"
|
||||||
{ "rename": { "field": "message2.qtype", "target_field": "dns.query.type", "ignore_missing": true } },
|
],
|
||||||
{ "rename": { "field": "message2.qtype_name", "target_field": "dns.query.type_name", "ignore_missing": true } },
|
"ignore_failure": true
|
||||||
{ "rename": { "field": "message2.rcode", "target_field": "dns.response.code", "ignore_missing": true } },
|
}
|
||||||
{ "rename": { "field": "message2.rcode_name", "target_field": "dns.response.code_name", "ignore_missing": true } },
|
},
|
||||||
{ "rename": { "field": "message2.AA", "target_field": "dns.authoritative", "ignore_missing": true } },
|
{
|
||||||
{ "rename": { "field": "message2.TC", "target_field": "dns.truncated", "ignore_missing": true } },
|
"json": {
|
||||||
{ "rename": { "field": "message2.RD", "target_field": "dns.recursion.desired", "ignore_missing": true } },
|
"field": "message",
|
||||||
{ "rename": { "field": "message2.RA", "target_field": "dns.recursion.available", "ignore_missing": true } },
|
"target_field": "message2",
|
||||||
{ "rename": { "field": "message2.Z", "target_field": "dns.reserved", "ignore_missing": true } },
|
"ignore_failure": true
|
||||||
{ "rename": { "field": "message2.answers", "target_field": "dns.answers.name", "ignore_missing": true } },
|
}
|
||||||
{ "foreach": {"field": "dns.answers.name","processor": {"pipeline": {"name": "common.ip_validation"}},"if": "ctx.dns != null && ctx.dns.answers != null && ctx.dns.answers.name != null","ignore_failure": true}},
|
},
|
||||||
{ "foreach": {"field": "temp._valid_ips","processor": {"append": {"field": "dns.resolved_ip","allow_duplicates": false,"value": "{{{_ingest._value}}}","ignore_failure": true}},"ignore_failure": true}},
|
{
|
||||||
{ "script": { "source": "if (ctx.dns.resolved_ip != null && ctx.dns.resolved_ip instanceof List) {\n ctx.dns.resolved_ip.removeIf(item -> item == null || item.toString().trim().isEmpty());\n }","ignore_failure": true }},
|
"dot_expander": {
|
||||||
{ "remove": {"field": ["temp"], "ignore_missing": true ,"ignore_failure": true } },
|
"field": "id.orig_h",
|
||||||
{ "rename": { "field": "message2.TTLs", "target_field": "dns.ttls", "ignore_missing": true } },
|
"path": "message2",
|
||||||
{ "rename": { "field": "message2.rejected", "target_field": "dns.query.rejected", "ignore_missing": true } },
|
"ignore_failure": true
|
||||||
{ "script": { "lang": "painless", "source": "ctx.dns.query.length = ctx.dns.query.name.length()", "ignore_failure": true } },
|
}
|
||||||
{ "set": { "if": "ctx._index == 'so-zeek'", "field": "_index", "value": "so-zeek_dns", "override": true } },
|
},
|
||||||
{ "pipeline": { "if": "ctx.dns?.query?.name != null && ctx.dns.query.name.contains('.')", "name": "dns.tld" } },
|
{
|
||||||
{ "pipeline": { "name": "zeek.common" } }
|
"rename": {
|
||||||
]
|
"field": "message2.proto",
|
||||||
|
"target_field": "network.transport",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.trans_id",
|
||||||
|
"target_field": "dns.id",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.rtt",
|
||||||
|
"target_field": "event.duration",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.query",
|
||||||
|
"target_field": "dns.query.name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.qclass",
|
||||||
|
"target_field": "dns.query.class",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.qclass_name",
|
||||||
|
"target_field": "dns.query.class_name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.qtype",
|
||||||
|
"target_field": "dns.query.type",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.qtype_name",
|
||||||
|
"target_field": "dns.query.type_name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.rcode",
|
||||||
|
"target_field": "dns.response.code",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.rcode_name",
|
||||||
|
"target_field": "dns.response.code_name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.AA",
|
||||||
|
"target_field": "dns.authoritative",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.TC",
|
||||||
|
"target_field": "dns.truncated",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.RD",
|
||||||
|
"target_field": "dns.recursion.desired",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.RA",
|
||||||
|
"target_field": "dns.recursion.available",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.Z",
|
||||||
|
"target_field": "dns.reserved",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.answers",
|
||||||
|
"target_field": "dns.answers.name",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"foreach": {
|
||||||
|
"field": "dns.answers.name",
|
||||||
|
"processor": {
|
||||||
|
"pipeline": {
|
||||||
|
"name": "common.ip_validation"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"if": "ctx.dns != null && ctx.dns.answers != null && ctx.dns.answers.name != null",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"foreach": {
|
||||||
|
"field": "temp._valid_ips",
|
||||||
|
"processor": {
|
||||||
|
"append": {
|
||||||
|
"field": "dns.resolved_ip",
|
||||||
|
"allow_duplicates": false,
|
||||||
|
"value": "{{{_ingest._value}}}",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"if": "ctx.dns != null && ctx.dns.answers != null && ctx.dns.answers.name != null",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"source": "if (ctx.dns.resolved_ip != null && ctx.dns.resolved_ip instanceof List) {\n ctx.dns.resolved_ip.removeIf(item -> item == null || item.toString().trim().isEmpty());\n }",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"remove": {
|
||||||
|
"field": [
|
||||||
|
"temp"
|
||||||
|
],
|
||||||
|
"ignore_missing": true,
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.TTLs",
|
||||||
|
"target_field": "dns.ttls",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rename": {
|
||||||
|
"field": "message2.rejected",
|
||||||
|
"target_field": "dns.query.rejected",
|
||||||
|
"ignore_missing": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"lang": "painless",
|
||||||
|
"source": "ctx.dns.query.length = ctx.dns.query.name.length()",
|
||||||
|
"ignore_failure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set": {
|
||||||
|
"if": "ctx._index == 'so-zeek'",
|
||||||
|
"field": "_index",
|
||||||
|
"value": "so-zeek_dns",
|
||||||
|
"override": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"if": "ctx.dns?.query?.name != null && ctx.dns.query.name.contains('.')",
|
||||||
|
"name": "dns.tld"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pipeline": {
|
||||||
|
"name": "zeek.common"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"description" : "zeek.dpd",
|
|
||||||
"processors" : [
|
|
||||||
{ "set": { "field": "event.dataset", "value": "dpd" } },
|
|
||||||
{ "remove": { "field": ["host"], "ignore_failure": true } },
|
|
||||||
{ "json": { "field": "message", "target_field": "message2", "ignore_failure": true } },
|
|
||||||
{ "dot_expander": { "field": "id.orig_h", "path": "message2", "ignore_failure": true } },
|
|
||||||
{ "rename": { "field": "message2.id.orig_h", "target_field": "source.ip", "ignore_missing": true } },
|
|
||||||
{ "dot_expander": { "field": "id.orig_p", "path": "message2", "ignore_failure": true } },
|
|
||||||
{ "rename": { "field": "message2.id.orig_p", "target_field": "source.port", "ignore_missing": true } },
|
|
||||||
{ "dot_expander": { "field": "id.resp_h", "path": "message2", "ignore_failure": true } },
|
|
||||||
{ "rename": { "field": "message2.id.resp_h", "target_field": "destination.ip", "ignore_missing": true } },
|
|
||||||
{ "dot_expander": { "field": "id.resp_p", "path": "message2", "ignore_failure": true } },
|
|
||||||
{ "rename": { "field": "message2.id.resp_p", "target_field": "destination.port", "ignore_missing": true } },
|
|
||||||
{ "rename": { "field": "message2.proto", "target_field": "network.protocol", "ignore_missing": true } },
|
|
||||||
{ "rename": { "field": "message2.analyzer", "target_field": "observer.analyzer", "ignore_missing": true } },
|
|
||||||
{ "rename": { "field": "message2.failure_reason", "target_field": "error.reason", "ignore_missing": true } },
|
|
||||||
{ "pipeline": { "name": "zeek.common" } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -131,6 +131,47 @@ elasticsearch:
|
|||||||
description: Maximum primary shard size. Once an index reaches this limit, it will be rolled over into a new index.
|
description: Maximum primary shard size. Once an index reaches this limit, it will be rolled over into a new index.
|
||||||
global: True
|
global: True
|
||||||
helpLink: elasticsearch.html
|
helpLink: elasticsearch.html
|
||||||
|
shrink:
|
||||||
|
method:
|
||||||
|
description: Shrink the index to a new index with fewer primary shards. Shrink operation is by count or size.
|
||||||
|
options:
|
||||||
|
- COUNT
|
||||||
|
- SIZE
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
|
forcedType: string
|
||||||
|
number_of_shards:
|
||||||
|
title: shard count
|
||||||
|
description: Desired shard count. Note that this value is only used when the shrink method selected is 'COUNT'.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
max_primary_shard_size:
|
||||||
|
title: max shard size
|
||||||
|
description: Desired shard size in gb/tb/pb eg. 100gb. Note that this value is only used when the shrink method selected is 'SIZE'.
|
||||||
|
regex: ^[0-9]+(?:gb|tb|pb)$
|
||||||
|
global: True
|
||||||
|
forcedType: string
|
||||||
|
advanced: True
|
||||||
|
allow_write_after_shrink:
|
||||||
|
description: Allow writes after shrink.
|
||||||
|
global: True
|
||||||
|
forcedType: bool
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments:
|
||||||
|
description: Reduce the number of segments in each index shard and clean up deleted documents.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
index_codec:
|
||||||
|
title: compression
|
||||||
|
description: Use higher compression for stored fields at the cost of slower performance.
|
||||||
|
forcedType: bool
|
||||||
|
global: True
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
cold:
|
cold:
|
||||||
min_age:
|
min_age:
|
||||||
description: Minimum age of index. ex. 60d - This determines when the index should be moved to the cold tier. While still searchable, this tier is typically optimized for lower storage costs rather than search speed. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and cold min_age set to 60 then there will be 30 days from index creation to rollover and then an additional 60 days before moving to cold tier.
|
description: Minimum age of index. ex. 60d - This determines when the index should be moved to the cold tier. While still searchable, this tier is typically optimized for lower storage costs rather than search speed. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and cold min_age set to 60 then there will be 30 days from index creation to rollover and then an additional 60 days before moving to cold tier.
|
||||||
@@ -144,6 +185,12 @@ elasticsearch:
|
|||||||
description: Used for index recovery after a node restart. Indices with higher priorities are recovered before indices with lower priorities.
|
description: Used for index recovery after a node restart. Indices with higher priorities are recovered before indices with lower priorities.
|
||||||
global: True
|
global: True
|
||||||
helpLink: elasticsearch.html
|
helpLink: elasticsearch.html
|
||||||
|
allocate:
|
||||||
|
number_of_replicas:
|
||||||
|
description: Set the number of replicas. Remains the same as the previous phase by default.
|
||||||
|
forcedType: int
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
warm:
|
warm:
|
||||||
min_age:
|
min_age:
|
||||||
description: Minimum age of index. ex. 30d - This determines when the index should be moved to the warm tier. Nodes in the warm tier generally don’t need to be as fast as those in the hot tier. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and warm min_age set to 30 then there will be 30 days from index creation to rollover and then an additional 30 days before moving to warm tier.
|
description: Minimum age of index. ex. 30d - This determines when the index should be moved to the warm tier. Nodes in the warm tier generally don’t need to be as fast as those in the hot tier. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and warm min_age set to 30 then there will be 30 days from index creation to rollover and then an additional 30 days before moving to warm tier.
|
||||||
@@ -158,6 +205,52 @@ elasticsearch:
|
|||||||
forcedType: int
|
forcedType: int
|
||||||
global: True
|
global: True
|
||||||
helpLink: elasticsearch.html
|
helpLink: elasticsearch.html
|
||||||
|
shrink:
|
||||||
|
method:
|
||||||
|
description: Shrink the index to a new index with fewer primary shards. Shrink operation is by count or size.
|
||||||
|
options:
|
||||||
|
- COUNT
|
||||||
|
- SIZE
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
|
number_of_shards:
|
||||||
|
title: shard count
|
||||||
|
description: Desired shard count. Note that this value is only used when the shrink method selected is 'COUNT'.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
max_primary_shard_size:
|
||||||
|
title: max shard size
|
||||||
|
description: Desired shard size in gb/tb/pb eg. 100gb. Note that this value is only used when the shrink method selected is 'SIZE'.
|
||||||
|
regex: ^[0-9]+(?:gb|tb|pb)$
|
||||||
|
global: True
|
||||||
|
forcedType: string
|
||||||
|
advanced: True
|
||||||
|
allow_write_after_shrink:
|
||||||
|
description: Allow writes after shrink.
|
||||||
|
global: True
|
||||||
|
forcedType: bool
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments:
|
||||||
|
description: Reduce the number of segments in each index shard and clean up deleted documents.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
index_codec:
|
||||||
|
title: compression
|
||||||
|
description: Use higher compression for stored fields at the cost of slower performance.
|
||||||
|
forcedType: bool
|
||||||
|
global: True
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
|
allocate:
|
||||||
|
number_of_replicas:
|
||||||
|
description: Set the number of replicas. Remains the same as the previous phase by default.
|
||||||
|
forcedType: int
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
delete:
|
delete:
|
||||||
min_age:
|
min_age:
|
||||||
description: Minimum age of index. ex. 90d - This determines when the index should be deleted. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and delete min_age set to 90 then there will be 30 days from index creation to rollover and then an additional 90 days before deletion.
|
description: Minimum age of index. ex. 90d - This determines when the index should be deleted. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and delete min_age set to 90 then there will be 30 days from index creation to rollover and then an additional 90 days before deletion.
|
||||||
@@ -287,6 +380,47 @@ elasticsearch:
|
|||||||
global: True
|
global: True
|
||||||
advanced: True
|
advanced: True
|
||||||
helpLink: elasticsearch.html
|
helpLink: elasticsearch.html
|
||||||
|
shrink:
|
||||||
|
method:
|
||||||
|
description: Shrink the index to a new index with fewer primary shards. Shrink operation is by count or size.
|
||||||
|
options:
|
||||||
|
- COUNT
|
||||||
|
- SIZE
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
|
forcedType: string
|
||||||
|
number_of_shards:
|
||||||
|
title: shard count
|
||||||
|
description: Desired shard count. Note that this value is only used when the shrink method selected is 'COUNT'.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
max_primary_shard_size:
|
||||||
|
title: max shard size
|
||||||
|
description: Desired shard size in gb/tb/pb eg. 100gb. Note that this value is only used when the shrink method selected is 'SIZE'.
|
||||||
|
regex: ^[0-9]+(?:gb|tb|pb)$
|
||||||
|
global: True
|
||||||
|
forcedType: string
|
||||||
|
advanced: True
|
||||||
|
allow_write_after_shrink:
|
||||||
|
description: Allow writes after shrink.
|
||||||
|
global: True
|
||||||
|
forcedType: bool
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments:
|
||||||
|
description: Reduce the number of segments in each index shard and clean up deleted documents.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
index_codec:
|
||||||
|
title: compression
|
||||||
|
description: Use higher compression for stored fields at the cost of slower performance.
|
||||||
|
forcedType: bool
|
||||||
|
global: True
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
warm:
|
warm:
|
||||||
min_age:
|
min_age:
|
||||||
description: Minimum age of index. ex. 30d - This determines when the index should be moved to the warm tier. Nodes in the warm tier generally don’t need to be as fast as those in the hot tier. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and warm min_age set to 30 then there will be 30 days from index creation to rollover and then an additional 30 days before moving to warm tier.
|
description: Minimum age of index. ex. 30d - This determines when the index should be moved to the warm tier. Nodes in the warm tier generally don’t need to be as fast as those in the hot tier. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and warm min_age set to 30 then there will be 30 days from index creation to rollover and then an additional 30 days before moving to warm tier.
|
||||||
@@ -314,6 +448,52 @@ elasticsearch:
|
|||||||
global: True
|
global: True
|
||||||
advanced: True
|
advanced: True
|
||||||
helpLink: elasticsearch.html
|
helpLink: elasticsearch.html
|
||||||
|
shrink:
|
||||||
|
method:
|
||||||
|
description: Shrink the index to a new index with fewer primary shards. Shrink operation is by count or size.
|
||||||
|
options:
|
||||||
|
- COUNT
|
||||||
|
- SIZE
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
|
number_of_shards:
|
||||||
|
title: shard count
|
||||||
|
description: Desired shard count. Note that this value is only used when the shrink method selected is 'COUNT'.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
max_primary_shard_size:
|
||||||
|
title: max shard size
|
||||||
|
description: Desired shard size in gb/tb/pb eg. 100gb. Note that this value is only used when the shrink method selected is 'SIZE'.
|
||||||
|
regex: ^[0-9]+(?:gb|tb|pb)$
|
||||||
|
global: True
|
||||||
|
forcedType: string
|
||||||
|
advanced: True
|
||||||
|
allow_write_after_shrink:
|
||||||
|
description: Allow writes after shrink.
|
||||||
|
global: True
|
||||||
|
forcedType: bool
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
|
forcemerge:
|
||||||
|
max_num_segments:
|
||||||
|
description: Reduce the number of segments in each index shard and clean up deleted documents.
|
||||||
|
global: True
|
||||||
|
forcedType: int
|
||||||
|
advanced: True
|
||||||
|
index_codec:
|
||||||
|
title: compression
|
||||||
|
description: Use higher compression for stored fields at the cost of slower performance.
|
||||||
|
forcedType: bool
|
||||||
|
global: True
|
||||||
|
default: False
|
||||||
|
advanced: True
|
||||||
|
allocate:
|
||||||
|
number_of_replicas:
|
||||||
|
description: Set the number of replicas. Remains the same as the previous phase by default.
|
||||||
|
forcedType: int
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
cold:
|
cold:
|
||||||
min_age:
|
min_age:
|
||||||
description: Minimum age of index. ex. 60d - This determines when the index should be moved to the cold tier. While still searchable, this tier is typically optimized for lower storage costs rather than search speed. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and cold min_age set to 60 then there will be 30 days from index creation to rollover and then an additional 60 days before moving to cold tier.
|
description: Minimum age of index. ex. 60d - This determines when the index should be moved to the cold tier. While still searchable, this tier is typically optimized for lower storage costs rather than search speed. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and cold min_age set to 60 then there will be 30 days from index creation to rollover and then an additional 60 days before moving to cold tier.
|
||||||
@@ -330,6 +510,12 @@ elasticsearch:
|
|||||||
global: True
|
global: True
|
||||||
advanced: True
|
advanced: True
|
||||||
helpLink: elasticsearch.html
|
helpLink: elasticsearch.html
|
||||||
|
allocate:
|
||||||
|
number_of_replicas:
|
||||||
|
description: Set the number of replicas. Remains the same as the previous phase by default.
|
||||||
|
forcedType: int
|
||||||
|
global: True
|
||||||
|
advanced: True
|
||||||
delete:
|
delete:
|
||||||
min_age:
|
min_age:
|
||||||
description: Minimum age of index. ex. 90d - This determines when the index should be deleted. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and delete min_age set to 90 then there will be 30 days from index creation to rollover and then an additional 90 days before deletion.
|
description: Minimum age of index. ex. 90d - This determines when the index should be deleted. It’s important to note that this is calculated relative to the rollover date (NOT the original creation date of the index). For example, if you have an index that is set to rollover after 30 days and delete min_age set to 90 then there will be 30 days from index creation to rollover and then an additional 90 days before deletion.
|
||||||
|
|||||||
66
salt/elasticsearch/ssl.sls
Normal file
66
salt/elasticsearch/ssl.sls
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# 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 'ca/map.jinja' import CA %}
|
||||||
|
|
||||||
|
# Create a cert for elasticsearch
|
||||||
|
elasticsearch_key:
|
||||||
|
x509.private_key_managed:
|
||||||
|
- name: /etc/pki/elasticsearch.key
|
||||||
|
- keysize: 4096
|
||||||
|
- backup: True
|
||||||
|
- new: True
|
||||||
|
{% if salt['file.file_exists']('/etc/pki/elasticsearch.key') -%}
|
||||||
|
- prereq:
|
||||||
|
- x509: /etc/pki/elasticsearch.crt
|
||||||
|
{%- endif %}
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
|
||||||
|
elasticsearch_crt:
|
||||||
|
x509.certificate_managed:
|
||||||
|
- name: /etc/pki/elasticsearch.crt
|
||||||
|
- ca_server: {{ CA.server }}
|
||||||
|
- signing_policy: registry
|
||||||
|
- private_key: /etc/pki/elasticsearch.key
|
||||||
|
- CN: {{ GLOBALS.hostname }}
|
||||||
|
- subjectAltName: DNS:{{ GLOBALS.hostname }}, IP:{{ GLOBALS.node_ip }}
|
||||||
|
- days_remaining: 7
|
||||||
|
- days_valid: 820
|
||||||
|
- backup: True
|
||||||
|
- timeout: 30
|
||||||
|
- retry:
|
||||||
|
attempts: 5
|
||||||
|
interval: 30
|
||||||
|
cmd.run:
|
||||||
|
- name: "/usr/bin/openssl pkcs12 -inkey /etc/pki/elasticsearch.key -in /etc/pki/elasticsearch.crt -export -out /etc/pki/elasticsearch.p12 -nodes -passout pass:"
|
||||||
|
- onchanges:
|
||||||
|
- x509: /etc/pki/elasticsearch.key
|
||||||
|
|
||||||
|
elastickeyperms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticsearch.key
|
||||||
|
- mode: 640
|
||||||
|
- group: 930
|
||||||
|
|
||||||
|
elasticp12perms:
|
||||||
|
file.managed:
|
||||||
|
- replace: False
|
||||||
|
- name: /etc/pki/elasticsearch.p12
|
||||||
|
- mode: 640
|
||||||
|
- group: 930
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{{sls}}_state_not_allowed:
|
||||||
|
test.fail_without_changes:
|
||||||
|
- name: {{sls}}_state_not_allowed
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
@@ -61,5 +61,55 @@
|
|||||||
{% do settings.index_template.template.settings.index.pop('sort') %}
|
{% do settings.index_template.template.settings.index.pop('sort') %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{# advanced ilm actions #}
|
||||||
|
{% if settings.policy is defined and settings.policy.phases is defined %}
|
||||||
|
{% set PHASE_NAMES = ["hot", "warm", "cold"] %}
|
||||||
|
{% for P in PHASE_NAMES %}
|
||||||
|
{% if settings.policy.phases[P] is defined and settings.policy.phases[P].actions is defined %}
|
||||||
|
{% set PHASE = settings.policy.phases[P].actions %}
|
||||||
|
{# remove allocate action if number_of_replicas isn't configured #}
|
||||||
|
{% if PHASE.allocate is defined %}
|
||||||
|
{% if PHASE.allocate.number_of_replicas is not defined or PHASE.allocate.number_of_replicas == "" %}
|
||||||
|
{% do PHASE.pop('allocate', none) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{# start shrink action #}
|
||||||
|
{% if PHASE.shrink is defined %}
|
||||||
|
{% if PHASE.shrink.method is defined %}
|
||||||
|
{% if PHASE.shrink.method == 'COUNT' and PHASE.shrink.number_of_shards is defined and PHASE.shrink.number_of_shards %}
|
||||||
|
{# remove max_primary_shard_size value when doing shrink operation by count vs size #}
|
||||||
|
{% do PHASE.shrink.pop('max_primary_shard_size', none) %}
|
||||||
|
{% elif PHASE.shrink.method == 'SIZE' and PHASE.shrink.max_primary_shard_size is defined and PHASE.shrink.max_primary_shard_size %}
|
||||||
|
{# remove number_of_shards value when doing shrink operation by size vs count #}
|
||||||
|
{% do PHASE.shrink.pop('number_of_shards', none) %}
|
||||||
|
{% else %}
|
||||||
|
{# method isn't defined or missing a required config number_of_shards/max_primary_shard_size #}
|
||||||
|
{% do PHASE.pop('shrink', none) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{# always remove shrink method since its only used for SOC config, not in the actual ilm policy #}
|
||||||
|
{% if PHASE.shrink is defined %}
|
||||||
|
{% do PHASE.shrink.pop('method', none) %}
|
||||||
|
{% endif %}
|
||||||
|
{# end shrink action #}
|
||||||
|
{# start force merge #}
|
||||||
|
{% if PHASE.forcemerge is defined %}
|
||||||
|
{% if PHASE.forcemerge.index_codec is defined and PHASE.forcemerge.index_codec %}
|
||||||
|
{% do PHASE.forcemerge.update({'index_codec': 'best_compression'}) %}
|
||||||
|
{% else %}
|
||||||
|
{% do PHASE.forcemerge.pop('index_codec', none) %}
|
||||||
|
{% endif %}
|
||||||
|
{% if PHASE.forcemerge.max_num_segments is not defined or not PHASE.forcemerge.max_num_segments %}
|
||||||
|
{# max_num_segments is empty, drop it #}
|
||||||
|
{% do PHASE.pop('forcemerge', none) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{# end force merge #}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% do ES_INDEX_SETTINGS.update({index | replace("_x_", "."): ES_INDEX_SETTINGS_GLOBAL_OVERRIDES[index]}) %}
|
{% do ES_INDEX_SETTINGS.update({index | replace("_x_", "."): ES_INDEX_SETTINGS_GLOBAL_OVERRIDES[index]}) %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -841,6 +841,10 @@
|
|||||||
"type": "long"
|
"type": "long"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"capture_file": {
|
||||||
|
"type": "keyword",
|
||||||
|
"ignore_above": 1024
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1164
salt/elasticsearch/tools/sbin/so-elasticsearch-retention-estimate
Executable file
1164
salt/elasticsearch/tools/sbin/so-elasticsearch-retention-estimate
Executable file
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,9 @@ set -e
|
|||||||
# Check to see if we have extracted the ca cert.
|
# Check to see if we have extracted the ca cert.
|
||||||
if [ ! -f /opt/so/saltstack/local/salt/elasticsearch/cacerts ]; then
|
if [ ! -f /opt/so/saltstack/local/salt/elasticsearch/cacerts ]; then
|
||||||
docker run -v /etc/pki/ca.crt:/etc/ssl/ca.crt --name so-elasticsearchca --user root --entrypoint jdk/bin/keytool {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elasticsearch:$ELASTIC_AGENT_TARBALL_VERSION -keystore /usr/share/elasticsearch/jdk/lib/security/cacerts -alias SOSCA -import -file /etc/ssl/ca.crt -storepass changeit -noprompt
|
docker run -v /etc/pki/ca.crt:/etc/ssl/ca.crt --name so-elasticsearchca --user root --entrypoint jdk/bin/keytool {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-elasticsearch:$ELASTIC_AGENT_TARBALL_VERSION -keystore /usr/share/elasticsearch/jdk/lib/security/cacerts -alias SOSCA -import -file /etc/ssl/ca.crt -storepass changeit -noprompt
|
||||||
docker cp so-elasticsearchca:/usr/share/elasticsearch/jdk/lib/security/cacerts /opt/so/saltstack/local/salt/elasticsearch/cacerts
|
# Make sure symbolic links are followed when copying from container
|
||||||
docker cp so-elasticsearchca:/etc/ssl/certs/ca-certificates.crt /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem
|
docker cp -L so-elasticsearchca:/usr/share/elasticsearch/jdk/lib/security/cacerts /opt/so/saltstack/local/salt/elasticsearch/cacerts
|
||||||
|
docker cp -L so-elasticsearchca:/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem
|
||||||
docker rm so-elasticsearchca
|
docker rm so-elasticsearchca
|
||||||
echo "" >> /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem
|
echo "" >> /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem
|
||||||
echo "sosca" >> /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem
|
echo "sosca" >> /opt/so/saltstack/local/salt/elasticsearch/tls-ca-bundle.pem
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ if [ ! -f $STATE_FILE_SUCCESS ]; then
|
|||||||
echo "Loading Security Onion index templates..."
|
echo "Loading Security Onion index templates..."
|
||||||
shopt -s extglob
|
shopt -s extglob
|
||||||
{% if GLOBALS.role == 'so-heavynode' %}
|
{% if GLOBALS.role == 'so-heavynode' %}
|
||||||
pattern="!(*1password*|*aws*|*azure*|*cloudflare*|*elastic_agent*|*fim*|*github*|*google*|*osquery*|*system*|*windows*)"
|
pattern="!(*1password*|*aws*|*azure*|*cloudflare*|*elastic_agent*|*fim*|*github*|*google*|*osquery*|*system*|*windows*|*endpoint*|*elasticsearch*|*generic*|*fleet_server*|*soc*)"
|
||||||
{% else %}
|
{% else %}
|
||||||
pattern="*"
|
pattern="*"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ used during VM provisioning to add dedicated NSM storage volumes.
|
|||||||
This command creates and attaches a volume with the following settings:
|
This command creates and attaches a volume with the following settings:
|
||||||
- VM Name: `vm1_sensor`
|
- VM Name: `vm1_sensor`
|
||||||
- Volume Size: `500` GB
|
- Volume Size: `500` GB
|
||||||
- Volume Path: `/nsm/libvirt/volumes/vm1_sensor-nsm.img`
|
- Volume Path: `/nsm/libvirt/volumes/vm1_sensor-nsm-<epoch_timestamp>.img`
|
||||||
- Device: `/dev/vdb` (virtio-blk)
|
- Device: `/dev/vdb` (virtio-blk)
|
||||||
- VM remains stopped after attachment
|
- VM remains stopped after attachment
|
||||||
|
|
||||||
@@ -75,7 +75,8 @@ used during VM provisioning to add dedicated NSM storage volumes.
|
|||||||
|
|
||||||
- The script automatically stops the VM if it's running before creating and attaching the volume.
|
- The script automatically stops the VM if it's running before creating and attaching the volume.
|
||||||
- Volumes are created with full pre-allocation for optimal performance.
|
- Volumes are created with full pre-allocation for optimal performance.
|
||||||
- Volume files are stored in `/nsm/libvirt/volumes/` with naming pattern `<vm_name>-nsm.img`.
|
- Volume files are stored in `/nsm/libvirt/volumes/` with naming pattern `<vm_name>-nsm-<epoch_timestamp>.img`.
|
||||||
|
- The epoch timestamp ensures unique volume names and prevents conflicts.
|
||||||
- Volumes are attached as `/dev/vdb` using virtio-blk for high performance.
|
- Volumes are attached as `/dev/vdb` using virtio-blk for high performance.
|
||||||
- The script checks available disk space before creating the volume.
|
- The script checks available disk space before creating the volume.
|
||||||
- Ownership is set to `qemu:qemu` with permissions `640`.
|
- Ownership is set to `qemu:qemu` with permissions `640`.
|
||||||
@@ -142,6 +143,7 @@ import socket
|
|||||||
import subprocess
|
import subprocess
|
||||||
import pwd
|
import pwd
|
||||||
import grp
|
import grp
|
||||||
|
import time
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from so_vm_utils import start_vm, stop_vm
|
from so_vm_utils import start_vm, stop_vm
|
||||||
@@ -242,10 +244,13 @@ def create_volume_file(vm_name, size_gb, logger):
|
|||||||
Raises:
|
Raises:
|
||||||
VolumeCreationError: If volume creation fails
|
VolumeCreationError: If volume creation fails
|
||||||
"""
|
"""
|
||||||
# Define volume path (directory already created in main())
|
# Generate epoch timestamp for unique volume naming
|
||||||
volume_path = os.path.join(VOLUME_DIR, f"{vm_name}-nsm.img")
|
epoch_timestamp = int(time.time())
|
||||||
|
|
||||||
# Check if volume already exists
|
# Define volume path with epoch timestamp for uniqueness
|
||||||
|
volume_path = os.path.join(VOLUME_DIR, f"{vm_name}-nsm-{epoch_timestamp}.img")
|
||||||
|
|
||||||
|
# Check if volume already exists (shouldn't be possible with timestamp)
|
||||||
if os.path.exists(volume_path):
|
if os.path.exists(volume_path):
|
||||||
logger.error(f"VOLUME: Volume already exists: {volume_path}")
|
logger.error(f"VOLUME: Volume already exists: {volume_path}")
|
||||||
raise VolumeCreationError(f"Volume already exists: {volume_path}")
|
raise VolumeCreationError(f"Volume already exists: {volume_path}")
|
||||||
|
|||||||
@@ -1,65 +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 'allowed_states.map.jinja' import allowed_states %}
|
|
||||||
{% if sls.split('.')[0] in allowed_states %}
|
|
||||||
|
|
||||||
include:
|
|
||||||
- idstools.sync_files
|
|
||||||
|
|
||||||
idstoolslogdir:
|
|
||||||
file.directory:
|
|
||||||
- name: /opt/so/log/idstools
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- makedirs: True
|
|
||||||
|
|
||||||
idstools_sbin:
|
|
||||||
file.recurse:
|
|
||||||
- name: /usr/sbin
|
|
||||||
- source: salt://idstools/tools/sbin
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- file_mode: 755
|
|
||||||
|
|
||||||
# If this is used, exclude so-rule-update
|
|
||||||
#idstools_sbin_jinja:
|
|
||||||
# file.recurse:
|
|
||||||
# - name: /usr/sbin
|
|
||||||
# - source: salt://idstools/tools/sbin_jinja
|
|
||||||
# - user: 939
|
|
||||||
# - group: 939
|
|
||||||
# - file_mode: 755
|
|
||||||
# - template: jinja
|
|
||||||
|
|
||||||
idstools_so-rule-update:
|
|
||||||
file.managed:
|
|
||||||
- name: /usr/sbin/so-rule-update
|
|
||||||
- source: salt://idstools/tools/sbin_jinja/so-rule-update
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- mode: 755
|
|
||||||
- template: jinja
|
|
||||||
|
|
||||||
suricatacustomdirsfile:
|
|
||||||
file.directory:
|
|
||||||
- name: /nsm/rules/detect-suricata/custom_file
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- makedirs: True
|
|
||||||
|
|
||||||
suricatacustomdirsurl:
|
|
||||||
file.directory:
|
|
||||||
- name: /nsm/rules/detect-suricata/custom_temp
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
{{sls}}_state_not_allowed:
|
|
||||||
test.fail_without_changes:
|
|
||||||
- name: {{sls}}_state_not_allowed
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
idstools:
|
|
||||||
enabled: False
|
|
||||||
config:
|
|
||||||
urls: []
|
|
||||||
ruleset: ETOPEN
|
|
||||||
oinkcode: ""
|
|
||||||
sids:
|
|
||||||
enabled: []
|
|
||||||
disabled: []
|
|
||||||
modify: []
|
|
||||||
@@ -1,31 +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 'allowed_states.map.jinja' import allowed_states %}
|
|
||||||
{% if sls.split('.')[0] in allowed_states %}
|
|
||||||
|
|
||||||
include:
|
|
||||||
- idstools.sostatus
|
|
||||||
|
|
||||||
so-idstools:
|
|
||||||
docker_container.absent:
|
|
||||||
- force: True
|
|
||||||
|
|
||||||
so-idstools_so-status.disabled:
|
|
||||||
file.comment:
|
|
||||||
- name: /opt/so/conf/so-status/so-status.conf
|
|
||||||
- regex: ^so-idstools$
|
|
||||||
|
|
||||||
so-rule-update:
|
|
||||||
cron.absent:
|
|
||||||
- identifier: so-rule-update
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
{{sls}}_state_not_allowed:
|
|
||||||
test.fail_without_changes:
|
|
||||||
- name: {{sls}}_state_not_allowed
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
@@ -1,91 +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 'allowed_states.map.jinja' import allowed_states %}
|
|
||||||
{% if sls.split('.')[0] in allowed_states %}
|
|
||||||
{% from 'docker/docker.map.jinja' import DOCKER %}
|
|
||||||
{% from 'vars/globals.map.jinja' import GLOBALS %}
|
|
||||||
{% set proxy = salt['pillar.get']('manager:proxy') %}
|
|
||||||
|
|
||||||
include:
|
|
||||||
- idstools.config
|
|
||||||
- idstools.sostatus
|
|
||||||
|
|
||||||
so-idstools:
|
|
||||||
docker_container.running:
|
|
||||||
- image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-idstools:{{ GLOBALS.so_version }}
|
|
||||||
- hostname: so-idstools
|
|
||||||
- user: socore
|
|
||||||
- networks:
|
|
||||||
- sobridge:
|
|
||||||
- ipv4_address: {{ DOCKER.containers['so-idstools'].ip }}
|
|
||||||
{% if proxy %}
|
|
||||||
- environment:
|
|
||||||
- http_proxy={{ proxy }}
|
|
||||||
- https_proxy={{ proxy }}
|
|
||||||
- no_proxy={{ salt['pillar.get']('manager:no_proxy') }}
|
|
||||||
{% if DOCKER.containers['so-idstools'].extra_env %}
|
|
||||||
{% for XTRAENV in DOCKER.containers['so-idstools'].extra_env %}
|
|
||||||
- {{ XTRAENV }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% elif DOCKER.containers['so-idstools'].extra_env %}
|
|
||||||
- environment:
|
|
||||||
{% for XTRAENV in DOCKER.containers['so-idstools'].extra_env %}
|
|
||||||
- {{ XTRAENV }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
- binds:
|
|
||||||
- /opt/so/conf/idstools/etc:/opt/so/idstools/etc:ro
|
|
||||||
- /opt/so/rules/nids/suri:/opt/so/rules/nids/suri:rw
|
|
||||||
- /nsm/rules/:/nsm/rules/:rw
|
|
||||||
{% if DOCKER.containers['so-idstools'].custom_bind_mounts %}
|
|
||||||
{% for BIND in DOCKER.containers['so-idstools'].custom_bind_mounts %}
|
|
||||||
- {{ BIND }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
- extra_hosts:
|
|
||||||
- {{ GLOBALS.manager }}:{{ GLOBALS.manager_ip }}
|
|
||||||
{% if DOCKER.containers['so-idstools'].extra_hosts %}
|
|
||||||
{% for XTRAHOST in DOCKER.containers['so-idstools'].extra_hosts %}
|
|
||||||
- {{ XTRAHOST }}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
- watch:
|
|
||||||
- file: idstoolsetcsync
|
|
||||||
- file: idstools_so-rule-update
|
|
||||||
|
|
||||||
delete_so-idstools_so-status.disabled:
|
|
||||||
file.uncomment:
|
|
||||||
- name: /opt/so/conf/so-status/so-status.conf
|
|
||||||
- regex: ^so-idstools$
|
|
||||||
|
|
||||||
so-rule-update:
|
|
||||||
cron.present:
|
|
||||||
- name: /usr/sbin/so-rule-update > /opt/so/log/idstools/download_cron.log 2>&1
|
|
||||||
- identifier: so-rule-update
|
|
||||||
- user: root
|
|
||||||
- minute: '1'
|
|
||||||
- hour: '7'
|
|
||||||
|
|
||||||
# order this last to give so-idstools container time to be ready
|
|
||||||
run_so-rule-update:
|
|
||||||
cmd.run:
|
|
||||||
- name: '/usr/sbin/so-rule-update > /opt/so/log/idstools/download_idstools_state.log 2>&1'
|
|
||||||
- require:
|
|
||||||
- docker_container: so-idstools
|
|
||||||
- onchanges:
|
|
||||||
- file: idstools_so-rule-update
|
|
||||||
- file: idstoolsetcsync
|
|
||||||
- file: synclocalnidsrules
|
|
||||||
- order: last
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
{{sls}}_state_not_allowed:
|
|
||||||
test.fail_without_changes:
|
|
||||||
- name: {{sls}}_state_not_allowed
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{%- set disabled_sids = salt['pillar.get']('idstools:sids:disabled', {}) -%}
|
|
||||||
# idstools - disable.conf
|
|
||||||
|
|
||||||
# Example of disabling a rule by signature ID (gid is optional).
|
|
||||||
# 1:2019401
|
|
||||||
# 2019401
|
|
||||||
|
|
||||||
# Example of disabling a rule by regular expression.
|
|
||||||
# - All regular expression matches are case insensitive.
|
|
||||||
# re:hearbleed
|
|
||||||
# re:MS(0[7-9]|10)-\d+
|
|
||||||
{%- if disabled_sids != None %}
|
|
||||||
{%- for sid in disabled_sids %}
|
|
||||||
{{ sid }}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endif %}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{%- set enabled_sids = salt['pillar.get']('idstools:sids:enabled', {}) -%}
|
|
||||||
# idstools-rulecat - enable.conf
|
|
||||||
|
|
||||||
# Example of enabling a rule by signature ID (gid is optional).
|
|
||||||
# 1:2019401
|
|
||||||
# 2019401
|
|
||||||
|
|
||||||
# Example of enabling a rule by regular expression.
|
|
||||||
# - All regular expression matches are case insensitive.
|
|
||||||
# re:hearbleed
|
|
||||||
# re:MS(0[7-9]|10)-\d+
|
|
||||||
{%- if enabled_sids != None %}
|
|
||||||
{%- for sid in enabled_sids %}
|
|
||||||
{{ sid }}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endif %}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{%- set modify_sids = salt['pillar.get']('idstools:sids:modify', {}) -%}
|
|
||||||
# idstools-rulecat - modify.conf
|
|
||||||
|
|
||||||
# Format: <sid> "<from>" "<to>"
|
|
||||||
|
|
||||||
# Example changing the seconds for rule 2019401 to 3600.
|
|
||||||
#2019401 "seconds \d+" "seconds 3600"
|
|
||||||
{%- if modify_sids != None %}
|
|
||||||
{%- for sid in modify_sids %}
|
|
||||||
{{ sid }}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endif %}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{%- from 'vars/globals.map.jinja' import GLOBALS -%}
|
|
||||||
{%- from 'soc/merged.map.jinja' import SOCMERGED -%}
|
|
||||||
--suricata-version=7.0.3
|
|
||||||
--merged=/opt/so/rules/nids/suri/all.rules
|
|
||||||
--output=/nsm/rules/detect-suricata/custom_temp
|
|
||||||
--local=/opt/so/rules/nids/suri/local.rules
|
|
||||||
{%- if GLOBALS.md_engine == "SURICATA" %}
|
|
||||||
--local=/opt/so/rules/nids/suri/extraction.rules
|
|
||||||
--local=/opt/so/rules/nids/suri/filters.rules
|
|
||||||
{%- endif %}
|
|
||||||
--url=http://{{ GLOBALS.manager }}:7788/suricata/emerging-all.rules
|
|
||||||
--disable=/opt/so/idstools/etc/disable.conf
|
|
||||||
--enable=/opt/so/idstools/etc/enable.conf
|
|
||||||
--modify=/opt/so/idstools/etc/modify.conf
|
|
||||||
{%- if SOCMERGED.config.server.modules.suricataengine.customRulesets %}
|
|
||||||
{%- for ruleset in SOCMERGED.config.server.modules.suricataengine.customRulesets %}
|
|
||||||
{%- if 'url' in ruleset %}
|
|
||||||
--url={{ ruleset.url }}
|
|
||||||
{%- elif 'file' in ruleset %}
|
|
||||||
--local={{ ruleset.file }}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endif %}
|
|
||||||
@@ -1,13 +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 'idstools/map.jinja' import IDSTOOLSMERGED %}
|
|
||||||
|
|
||||||
include:
|
|
||||||
{% if IDSTOOLSMERGED.enabled %}
|
|
||||||
- idstools.enabled
|
|
||||||
{% else %}
|
|
||||||
- idstools.disabled
|
|
||||||
{% endif %}
|
|
||||||
@@ -1,7 +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. #}
|
|
||||||
|
|
||||||
{% import_yaml 'idstools/defaults.yaml' as IDSTOOLSDEFAULTS with context %}
|
|
||||||
{% set IDSTOOLSMERGED = salt['pillar.get']('idstools', IDSTOOLSDEFAULTS.idstools, merge=True) %}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Add your custom Suricata rules in this file.
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
idstools:
|
|
||||||
enabled:
|
|
||||||
description: Enables or disables the IDStools process which is used by the Detection system.
|
|
||||||
config:
|
|
||||||
oinkcode:
|
|
||||||
description: Enter your registration code or oinkcode for paid NIDS rulesets.
|
|
||||||
title: Registration Code
|
|
||||||
global: True
|
|
||||||
forcedType: string
|
|
||||||
helpLink: rules.html
|
|
||||||
ruleset:
|
|
||||||
description: 'Defines the ruleset you want to run. Options are ETOPEN or ETPRO. Once you have changed the ruleset here, you will need to wait for the rule update to take place (every 24 hours), or you can force the update by nagivating to Detections --> Options dropdown menu --> Suricata --> Full Update. WARNING! Changing the ruleset will remove all existing non-overlapping Suricata rules of the previous ruleset and their associated overrides. This removal cannot be undone.'
|
|
||||||
global: True
|
|
||||||
regex: ETPRO\b|ETOPEN\b
|
|
||||||
helpLink: rules.html
|
|
||||||
urls:
|
|
||||||
description: This is a list of additional rule download locations. This feature is currently disabled.
|
|
||||||
global: True
|
|
||||||
multiline: True
|
|
||||||
forcedType: "[]string"
|
|
||||||
readonly: True
|
|
||||||
helpLink: rules.html
|
|
||||||
sids:
|
|
||||||
disabled:
|
|
||||||
description: Contains the list of NIDS rules (or regex patterns) disabled across the grid. This setting is readonly; Use the Detections screen to disable rules.
|
|
||||||
global: True
|
|
||||||
multiline: True
|
|
||||||
forcedType: "[]string"
|
|
||||||
regex: \d*|re:.*
|
|
||||||
helpLink: managing-alerts.html
|
|
||||||
readonlyUi: True
|
|
||||||
advanced: true
|
|
||||||
enabled:
|
|
||||||
description: Contains the list of NIDS rules (or regex patterns) enabled across the grid. This setting is readonly; Use the Detections screen to enable rules.
|
|
||||||
global: True
|
|
||||||
multiline: True
|
|
||||||
forcedType: "[]string"
|
|
||||||
regex: \d*|re:.*
|
|
||||||
helpLink: managing-alerts.html
|
|
||||||
readonlyUi: True
|
|
||||||
advanced: true
|
|
||||||
modify:
|
|
||||||
description: Contains the list of NIDS rules (SID "REGEX_SEARCH_TERM" "REGEX_REPLACE_TERM"). This setting is readonly; Use the Detections screen to modify rules.
|
|
||||||
global: True
|
|
||||||
multiline: True
|
|
||||||
forcedType: "[]string"
|
|
||||||
helpLink: managing-alerts.html
|
|
||||||
readonlyUi: True
|
|
||||||
advanced: true
|
|
||||||
rules:
|
|
||||||
local__rules:
|
|
||||||
description: Contains the list of custom NIDS rules applied to the grid. This setting is readonly; Use the Detections screen to adjust rules.
|
|
||||||
file: True
|
|
||||||
global: True
|
|
||||||
advanced: True
|
|
||||||
title: Local Rules
|
|
||||||
helpLink: local-rules.html
|
|
||||||
readonlyUi: True
|
|
||||||
filters__rules:
|
|
||||||
description: If you are using Suricata for metadata, then you can set custom filters for that metadata here.
|
|
||||||
file: True
|
|
||||||
global: True
|
|
||||||
advanced: True
|
|
||||||
title: Filter Rules
|
|
||||||
helpLink: suricata.html
|
|
||||||
extraction__rules:
|
|
||||||
description: If you are using Suricata for metadata, then you can set a list of MIME types for file extraction here.
|
|
||||||
file: True
|
|
||||||
global: True
|
|
||||||
advanced: True
|
|
||||||
title: Extraction Rules
|
|
||||||
helpLink: suricata.html
|
|
||||||
@@ -1,37 +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.
|
|
||||||
|
|
||||||
|
|
||||||
idstoolsdir:
|
|
||||||
file.directory:
|
|
||||||
- name: /opt/so/conf/idstools/etc
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- makedirs: True
|
|
||||||
|
|
||||||
idstoolsetcsync:
|
|
||||||
file.recurse:
|
|
||||||
- name: /opt/so/conf/idstools/etc
|
|
||||||
- source: salt://idstools/etc
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- template: jinja
|
|
||||||
|
|
||||||
rulesdir:
|
|
||||||
file.directory:
|
|
||||||
- name: /opt/so/rules/nids/suri
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- makedirs: True
|
|
||||||
|
|
||||||
# Don't show changes because all.rules can be large
|
|
||||||
synclocalnidsrules:
|
|
||||||
file.recurse:
|
|
||||||
- name: /opt/so/rules/nids/suri/
|
|
||||||
- source: salt://idstools/rules/
|
|
||||||
- user: 939
|
|
||||||
- group: 939
|
|
||||||
- show_changes: False
|
|
||||||
- include_pat: 'E@.rules'
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/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 idstools $1
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/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 idstools $1
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# if this script isn't already running
|
|
||||||
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
|
|
||||||
|
|
||||||
. /usr/sbin/so-common
|
|
||||||
|
|
||||||
{%- from 'vars/globals.map.jinja' import GLOBALS %}
|
|
||||||
{%- from 'idstools/map.jinja' import IDSTOOLSMERGED %}
|
|
||||||
|
|
||||||
{%- set proxy = salt['pillar.get']('manager:proxy') %}
|
|
||||||
{%- set noproxy = salt['pillar.get']('manager:no_proxy', '') %}
|
|
||||||
|
|
||||||
{%- if proxy %}
|
|
||||||
# Download the rules from the internet
|
|
||||||
export http_proxy={{ proxy }}
|
|
||||||
export https_proxy={{ proxy }}
|
|
||||||
export no_proxy="{{ noproxy }}"
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
mkdir -p /nsm/rules/suricata
|
|
||||||
chown -R socore:socore /nsm/rules/suricata
|
|
||||||
{%- if not GLOBALS.airgap %}
|
|
||||||
# Download the rules from the internet
|
|
||||||
{%- if IDSTOOLSMERGED.config.ruleset == 'ETOPEN' %}
|
|
||||||
docker exec so-idstools idstools-rulecat -v --suricata-version 7.0.3 -o /nsm/rules/suricata/ --merged=/nsm/rules/suricata/emerging-all.rules --force
|
|
||||||
{%- elif IDSTOOLSMERGED.config.ruleset == 'ETPRO' %}
|
|
||||||
docker exec so-idstools idstools-rulecat -v --suricata-version 7.0.3 -o /nsm/rules/suricata/ --merged=/nsm/rules/suricata/emerging-all.rules --force --etpro={{ IDSTOOLSMERGED.config.oinkcode }}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
|
|
||||||
argstr=""
|
|
||||||
for arg in "$@"; do
|
|
||||||
argstr="${argstr} \"${arg}\""
|
|
||||||
done
|
|
||||||
|
|
||||||
docker exec so-idstools /bin/bash -c "cd /opt/so/idstools/etc && idstools-rulecat --force ${argstr}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user