Compare commits

..
Author SHA1 Message Date
defensivedepth 99322cf26a Add additional mapping 2026-10-01 15:24:52 -04:00
defensivedepth 2a4611df45 Add caseless mappings 2026-10-01 10:48:55 -04:00
11 changed files with 249 additions and 604 deletions

No files matched your search

+5
View File
@@ -3309,6 +3309,7 @@ elasticsearch:
composed_of:
- event-mappings
- logs-system.security@package
- so-fleet_system.security_caseless-1
- logs-system.security@custom
- so-fleet_integrations.ip_mappings-1
- so-fleet_globals-1
@@ -4175,6 +4176,7 @@ elasticsearch:
index_template:
composed_of:
- logs-windows.forwarded@package
- so-fleet_process_caseless-1
- logs-windows.forwarded@custom
- so-fleet_integrations.ip_mappings-1
- so-fleet_globals-1
@@ -4224,6 +4226,7 @@ elasticsearch:
index_template:
composed_of:
- logs-windows.powershell@package
- so-fleet_process_caseless-1
- logs-windows.powershell@custom
- so-fleet_integrations.ip_mappings-1
- so-fleet_globals-1
@@ -4273,6 +4276,7 @@ elasticsearch:
index_template:
composed_of:
- logs-windows.powershell_operational@package
- so-fleet_process_caseless-1
- logs-windows.powershell_operational@custom
- so-fleet_integrations.ip_mappings-1
- so-fleet_globals-1
@@ -4322,6 +4326,7 @@ elasticsearch:
index_template:
composed_of:
- logs-windows.sysmon_operational@package
- so-fleet_process_caseless-1
- logs-windows.sysmon_operational@custom
- so-fleet_integrations.ip_mappings-1
- so-fleet_globals-1
@@ -0,0 +1,123 @@
{
"_meta": {
"managed_by": "security_onion",
"managed": true,
"description": "Adds .caseless for Lucene queries. Restates each field's package type and .text."
},
"template": {
"mappings": {
"properties": {
"process": {
"properties": {
"executable": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
},
"name": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
},
"command_line": {
"type": "wildcard",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
},
"parent": {
"properties": {
"executable": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
},
"name": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
},
"command_line": {
"type": "wildcard",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
}
}
}
}
},
"file": {
"properties": {
"path": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
},
"text": {
"type": "match_only_text"
}
}
}
}
}
}
}
}
}
@@ -0,0 +1,80 @@
{
"_meta": {
"managed_by": "security_onion",
"managed": true,
"description": "Adds .caseless for Lucene queries. Keeps each field's existing keyword type."
},
"template": {
"mappings": {
"properties": {
"process": {
"properties": {
"command_line": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
}
}
},
"parent": {
"properties": {
"executable": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
}
}
},
"name": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
}
}
},
"command_line": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
}
}
}
}
}
}
},
"file": {
"properties": {
"path": {
"type": "keyword",
"ignore_above": 1024,
"fields": {
"caseless": {
"type": "keyword",
"ignore_above": 1024,
"normalizer": "lowercase"
}
}
}
}
}
}
}
}
}
+1 -2
View File
@@ -42,8 +42,7 @@ def loadYaml(filename):
try:
with open(filename, "r") as file:
content = file.read()
loaded = yaml.safe_load(content)
return loaded if loaded is not None else {}
return yaml.safe_load(content)
except FileNotFoundError:
print(f"File not found: {filename}", file=sys.stderr)
sys.exit(1)
-97
View File
@@ -95,20 +95,6 @@ class TestRemove(unittest.TestCase):
expected = "key1:\n child1: 123\n child2:\n deep2: ab\nkey2: false\n"
self.assertEqual(actual, expected)
def test_remove_empty_file(self):
filename = "/tmp/so-yaml_test-remove-empty.yaml"
file = open(filename, "w")
file.close()
code = soyaml.remove([filename, "key1"])
self.assertEqual(code, 0)
file = open(filename, "r")
actual = file.read()
file.close()
self.assertEqual(actual, "{}\n")
def test_remove_missing_args(self):
with patch('sys.exit', new=MagicMock()) as sysmock:
with patch('sys.stderr', new=StringIO()) as mock_stderr:
@@ -308,36 +294,6 @@ class TestRemove(unittest.TestCase):
expected = "key1:\n child1: 123\n child2:\n deep1: 45\n deep2: d\nkey2: false\nkey3:\n- e\n- f\n- g\n"
self.assertEqual(actual, expected)
def test_add_empty_file(self):
filename = "/tmp/so-yaml_test-add-empty.yaml"
file = open(filename, "w")
file.close()
code = soyaml.add([filename, "telegraf.output", "BOTH"])
self.assertEqual(code, 0)
file = open(filename, "r")
actual = file.read()
file.close()
expected = "telegraf:\n output: BOTH\n"
self.assertEqual(actual, expected)
def test_add_empty_file_simple(self):
filename = "/tmp/so-yaml_test-add-empty-simple.yaml"
file = open(filename, "w")
file.close()
code = soyaml.add([filename, "telegraf", "BOTH"])
self.assertEqual(code, 0)
file = open(filename, "r")
actual = file.read()
file.close()
expected = "telegraf: BOTH\n"
self.assertEqual(actual, expected)
def test_replace_missing_arg(self):
with patch('sys.exit', new=MagicMock()) as sysmock:
with patch('sys.stderr', new=StringIO()) as mock_stderr:
@@ -390,21 +346,6 @@ class TestRemove(unittest.TestCase):
expected = "key1:\n child1: 123\n child2:\n deep1: 46\nkey2: false\nkey3:\n- e\n- f\n- g\n"
self.assertEqual(actual, expected)
def test_replace_empty_file(self):
filename = "/tmp/so-yaml_test-replace-empty.yaml"
file = open(filename, "w")
file.close()
code = soyaml.replace([filename, "telegraf.output", "BOTH"])
self.assertEqual(code, 0)
file = open(filename, "r")
actual = file.read()
file.close()
expected = "telegraf:\n output: BOTH\n"
self.assertEqual(actual, expected)
def test_convert(self):
self.assertEqual(soyaml.convertType("foo"), "foo")
self.assertEqual(soyaml.convertType("foo.bar"), "foo.bar")
@@ -565,18 +506,6 @@ class TestRemove(unittest.TestCase):
self.assertEqual(result, 2)
self.assertEqual("", mock_stdout.getvalue())
def test_get_empty_file(self):
with patch('sys.stdout', new=StringIO()) as mock_stdout:
with patch('sys.stderr', new=StringIO()) as mock_stderr:
filename = "/tmp/so-yaml_test-get-empty.yaml"
file = open(filename, "w")
file.close()
result = soyaml.get([filename, "telegraf.output"])
self.assertEqual(result, 2)
self.assertEqual("", mock_stdout.getvalue())
self.assertIn("Key 'telegraf.output' not found by so-yaml.py", mock_stderr.getvalue())
def test_get_usage(self):
with patch('sys.exit', new=MagicMock()) as sysmock:
with patch('sys.stderr', new=StringIO()) as mock_stderr:
@@ -1062,29 +991,3 @@ class TestLoadYaml(unittest.TestCase):
soyaml.loadYaml("/tmp/so-yaml_test-unreadable.yaml")
sysmock.assert_called_with(1)
self.assertIn("Error reading file", mock_stderr.getvalue())
def test_load_yaml_empty_file(self):
filename = "/tmp/so-yaml_test-load-empty.yaml"
file = open(filename, "w")
file.close()
result = soyaml.loadYaml(filename)
self.assertEqual(result, {})
def test_load_yaml_whitespace_only(self):
filename = "/tmp/so-yaml_test-load-whitespace.yaml"
file = open(filename, "w")
file.write(" \n\n \n")
file.close()
result = soyaml.loadYaml(filename)
self.assertEqual(result, {})
def test_load_yaml_comments_only(self):
filename = "/tmp/so-yaml_test-load-comments.yaml"
file = open(filename, "w")
file.write("# Just a comment\n# Another comment\n")
file.close()
result = soyaml.loadYaml(filename)
self.assertEqual(result, {})
+6 -17
View File
@@ -120,30 +120,19 @@ crondetectionsbackup:
socsigmafinalpipeline:
file.managed:
- name: /opt/so/conf/soc/sigma_pipelines/sigma_final_pipeline.yml
- name: /opt/so/conf/soc/sigma_final_pipeline.yaml
- source: salt://soc/files/soc/sigma_final_pipeline.yaml
- user: 939
- group: 939
- mode: 600
- makedirs: True
# sigma-cli loads every *.yml here; clean removes anything else
socsigmapipelines:
file.recurse:
- name: /opt/so/conf/soc/sigma_pipelines
- source: salt://soc/files/soc/sigma_pipelines
socsigmasopipeline:
file.managed:
- name: /opt/so/conf/soc/sigma_so_pipeline.yaml
- source: salt://soc/files/soc/sigma_so_pipeline.yaml
- user: 939
- group: 939
- file_mode: 600
- clean: True
- require:
- file: socsigmafinalpipeline
socsigmapipelinesold:
file.absent:
- names:
- /opt/so/conf/soc/sigma_final_pipeline.yaml
- /opt/so/conf/soc/sigma_so_pipeline.yaml
- mode: 600
socsigmaplaybookpipeline:
file.managed:
+2 -2
View File
@@ -47,8 +47,9 @@ so-soc:
{% endif %}
- /opt/so/conf/soc/motd.md:/opt/sensoroni/html/motd.md:ro
- /opt/so/conf/soc/banner.md:/opt/sensoroni/html/login/banner.md:ro
- /opt/so/conf/soc/sigma_pipelines:/opt/sensoroni/sigma_pipelines:ro
- /opt/so/conf/soc/sigma_so_pipeline.yaml:/opt/sensoroni/sigma_so_pipeline.yaml:ro
- /opt/so/conf/soc/sigma_playbook_pipeline.yaml:/opt/sensoroni/sigma_playbook_pipeline.yaml:ro
- /opt/so/conf/soc/sigma_final_pipeline.yaml:/opt/sensoroni/sigma_final_pipeline.yaml:ro
- /opt/so/conf/soc/playbook_placeholder_map.yaml:/opt/sensoroni/playbook_placeholder_map.yaml:ro
- /opt/so/conf/soc/playbook_placeholder_map_custom.yaml:/opt/sensoroni/playbook_placeholder_map_custom.yaml:ro
- /opt/so/conf/soc/custom.js:/opt/sensoroni/html/js/custom.js:ro
@@ -106,7 +107,6 @@ so-soc:
- file: socclientsroles
- file: socplaybookplaceholdermap
- file: socplaybookplaceholdermapcustom
- file: socsigmapipelines
delete_so-soc_so-status.disabled:
file.uncomment:
@@ -1,477 +0,0 @@
name: Security Onion ES|QL Pipeline
# ES|QL query settings
priority: 92
transformations:
- id: esql_default_index
type: set_state
key: index
val: .ds-logs-*
- id: esql_source_metadata
type: set_state
key: metadata
val: "_id, _index, _source"
- id: esql_source_keep
type: set_state
key: keep
val: "_id, _index, _source"
# unmapped fields read as null instead of failing the query
- id: esql_unmapped_fields
type: set_state
key: unmapped_fields
val: nullify
# FROM targets per logsource, any namespace; later entries win, correlations get the union
- id: esql_index_process_creation
type: set_state
key: index
val:
- .ds-logs-endpoint.events.process-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-system.security-*
- .ds-logs-windows.powershell-*
- .ds-logs-windows.forwarded-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-auditd_manager.auditd-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
category: process_creation
- id: esql_index_process_creation_windows
type: set_state
key: index
val:
- .ds-logs-endpoint.events.process-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-system.security-*
- .ds-logs-windows.powershell-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: windows
category: process_creation
- id: esql_index_process_creation_linux
type: set_state
key: index
val:
- .ds-logs-endpoint.events.process-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-auditd_manager.auditd-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: linux
category: process_creation
- id: esql_index_process_creation_macos
type: set_state
key: index
val:
- .ds-logs-endpoint.events.process-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: macos
category: process_creation
- id: esql_index_file
type: set_state
key: index
val:
- .ds-logs-endpoint.events.file-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: file_event
- type: logsource
category: file_delete
- type: logsource
category: file_rename
- type: logsource
category: file_change
- type: logsource
category: file_access
- id: esql_index_file_windows
type: set_state
key: index
val:
- .ds-logs-endpoint.events.file-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: windows
category: file_event
- type: logsource
product: windows
category: file_delete
- type: logsource
product: windows
category: file_rename
- type: logsource
product: windows
category: file_change
- type: logsource
product: windows
category: file_access
- id: esql_index_file_linux
type: set_state
key: index
val:
- .ds-logs-endpoint.events.file-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: linux
category: file_event
- type: logsource
product: linux
category: file_delete
- type: logsource
product: linux
category: file_rename
- type: logsource
product: linux
category: file_change
- type: logsource
product: linux
category: file_access
- id: esql_index_file_macos
type: set_state
key: index
val:
- .ds-logs-endpoint.events.file-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: macos
category: file_event
- type: logsource
product: macos
category: file_delete
- type: logsource
product: macos
category: file_rename
- type: logsource
product: macos
category: file_change
- type: logsource
product: macos
category: file_access
- id: esql_index_registry
type: set_state
key: index
val:
- .ds-logs-endpoint.events.registry-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: registry_set
- type: logsource
category: registry_add
- type: logsource
category: registry_delete
- type: logsource
category: registry_event
- id: esql_index_library
type: set_state
key: index
val:
- .ds-logs-endpoint.events.library-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: image_load
- type: logsource
category: driver_load
- id: esql_index_endpoint_network
type: set_state
key: index
val:
- .ds-logs-endpoint.events.network-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: network_connection
- type: logsource
category: dns_query
- id: esql_index_endpoint_network_windows
type: set_state
key: index
val:
- .ds-logs-endpoint.events.network-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: windows
category: network_connection
- type: logsource
product: windows
category: dns_query
- id: esql_index_endpoint_network_linux
type: set_state
key: index
val:
- .ds-logs-endpoint.events.network-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: linux
category: network_connection
- type: logsource
product: linux
category: dns_query
- id: esql_index_endpoint_network_macos
type: set_state
key: index
val:
- .ds-logs-endpoint.events.network-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: macos
category: network_connection
- type: logsource
product: macos
category: dns_query
- id: esql_index_sysmon_only
type: set_state
key: index
val:
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: process_access
- type: logsource
category: create_remote_thread
- type: logsource
category: pipe_created
- type: logsource
category: create_stream_hash
- type: logsource
category: wmi_event
- type: logsource
category: raw_access_thread
- type: logsource
category: process_tampering
- type: logsource
category: sysmon_status
- type: logsource
category: sysmon_error
- type: logsource
category: file_executable_detected
- type: logsource
category: file_block_executable
- type: logsource
category: file_block_shredding
- type: logsource
category: clipboard_capture
- type: logsource
product: windows
service: sysmon
- id: esql_index_ps_operational
type: set_state
key: index
val:
- .ds-logs-windows.powershell_operational-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: ps_script
- type: logsource
category: ps_module
- type: logsource
product: windows
service: powershell
- id: esql_index_ps_classic
type: set_state
key: index
val:
- .ds-logs-windows.powershell-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: ps_classic_start
- type: logsource
category: ps_classic_provider_start
- type: logsource
category: ps_classic_script
- type: logsource
product: windows
service: powershell-classic
- id: esql_index_win_security
type: set_state
key: index
val:
- .ds-logs-system.security-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: windows
service: security
- id: esql_index_win_system
type: set_state
key: index
val:
- .ds-logs-system.system-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: windows
service: system
- id: esql_index_win_application
type: set_state
key: index
val:
- .ds-logs-system.application-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: windows
service: application
- id: esql_index_linux_auth
type: set_state
key: index
val:
- .ds-logs-system.auth-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
product: linux
service: auth
- type: logsource
product: linux
service: sshd
- type: logsource
product: linux
service: sudo
- id: esql_index_linux_syslog
type: set_state
key: index
val:
- .ds-logs-system.syslog-*
- .ds-logs-syslog-so-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: linux
service: syslog
- id: esql_index_linux_auditd
type: set_state
key: index
val:
- .ds-logs-auditd_manager.auditd-*
- .ds-logs-auditd.log-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: linux
service: auditd
- id: esql_index_network
type: set_state
key: index
val:
- .ds-logs-zeek-so-*
- .ds-logs-suricata-so-*
- .ds-logs-suricata.alerts-so-*
- .ds-logs-endpoint.events.network-*
- .ds-logs-windows.sysmon_operational-*
- .ds-logs-sysmon_linux.log-*
- .ds-logs-windows.forwarded-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
category: network
- id: esql_index_so_network
type: set_state
key: index
val:
- .ds-logs-zeek-so-*
- .ds-logs-suricata-so-*
- .ds-logs-import-so-*
rule_cond_op: or
rule_conditions:
- type: logsource
category: network
service: connection
- type: logsource
category: network
service: dns
- type: logsource
category: network
service: http
- type: logsource
category: network
service: file
- type: logsource
category: network
service: x509
- type: logsource
category: network
service: ssl
- type: logsource
category: network
service: ssh
- type: logsource
category: dns
- id: esql_index_zeek
type: set_state
key: index
val:
- .ds-logs-zeek-so-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: zeek
- id: esql_index_opencanary
type: set_state
key: index
val:
- .ds-logs-idh-so-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: opencanary
- id: esql_index_kratos
type: set_state
key: index
val:
- .ds-logs-kratos-so-*
- .ds-logs-import-so-*
rule_conditions:
- type: logsource
product: kratos
@@ -2,13 +2,13 @@ name: Security Onion - Playbook Pipeline
priority: 97
transformations:
# Route to lowercase-normalized .caseless subfields for case-insensitive matching.
# file.path.caseless exists on Defend only (Sysmon file events lack it);
# registry.path / dll.path / file.name have no .caseless on any source.
- id: case_insensitive_string_fields
type: field_name_mapping
mapping:
process.executable: process.executable.caseless
process.parent.executable: process.parent.executable.caseless
process.parent.name: process.parent.name.caseless
process.command_line: process.command_line.caseless
process.parent.command_line: process.parent.command_line.caseless
file.path: file.path.caseless
@@ -14,6 +14,28 @@ transformations:
- process.args
- related.ip
- dns.resolved_ip
- id: esql_default_index
type: set_state
key: index
val: .ds-logs-*
- id: esql_source_metadata
type: set_state
key: metadata
val: "_id, _index, _source"
- id: esql_source_keep
type: set_state
key: keep
val: "_id, _index, _source"
# Not every source maps .caseless; EQL/ES|QL already match case-insensitively.
- id: caseless_to_parent_fields
type: field_name_mapping
mapping:
process.executable.caseless: process.executable
process.name.caseless: process.name
process.parent.executable.caseless: process.parent.executable
process.parent.name.caseless: process.parent.name
target.process.executable.caseless: target.process.executable
target.process.name.caseless: target.process.name
- id: baseline_field_name_mapping
type: field_name_mapping
mapping:
+9 -8
View File
@@ -862,14 +862,15 @@ soc:
global: True
forcedType: bool
automations:
description: Scheduled automations for the Onion AI assistant, managed from the Agent Studio.
global: True
advanced: True
readonlyUi: True
storage: db
forcedType: string
syntax: json
helpLink: onion-ai
template:
description: Scheduled automations for the Onion AI assistant, managed from the Agent Studio. Each automation is stored under its own generated ID so its history and rollback are independent of every other automation.
global: True
advanced: False
readonlyUi: True
duplicates: True
forcedType: string
syntax: json
helpLink: onion-ai
agents:
description: Agent definitions for the Onion AI assistant, managed from the Agent Studio. An entry naming a system agent overrides only the fields an admin may change; everything else comes from the built-in definition.
global: True