mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2026-05-10 21:30:30 +02:00
Merge pull request #15867 from Security-Onion-Solutions/fixhype
sanitize minion ids for hypervisor reactors / orchestration
This commit is contained in:
@@ -3,7 +3,14 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
{% set hypervisor = pillar.minion_id %}
|
{% set hypervisor = pillar.get('minion_id', '') %}
|
||||||
|
|
||||||
|
{% if not hypervisor|regex_match('^([A-Za-z0-9._-]{1,253})$') %}
|
||||||
|
{% do salt.log.error('delete_hypervisor_orch: refusing unsafe minion_id=' ~ hypervisor) %}
|
||||||
|
delete_hypervisor_invalid_minion_id:
|
||||||
|
test.fail_without_changes:
|
||||||
|
- name: delete_hypervisor_invalid_minion_id
|
||||||
|
{% else %}
|
||||||
|
|
||||||
ensure_hypervisor_mine_deleted:
|
ensure_hypervisor_mine_deleted:
|
||||||
salt.function:
|
salt.function:
|
||||||
@@ -20,3 +27,5 @@ update_salt_cloud_profile:
|
|||||||
- sls:
|
- sls:
|
||||||
- salt.cloud.config
|
- salt.cloud.config
|
||||||
- concurrent: True
|
- concurrent: True
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@@ -12,7 +12,14 @@
|
|||||||
{% if 'vrt' in salt['pillar.get']('features', []) %}
|
{% if 'vrt' in salt['pillar.get']('features', []) %}
|
||||||
|
|
||||||
{% do salt.log.debug('vm_pillar_clean_orch: Running') %}
|
{% do salt.log.debug('vm_pillar_clean_orch: Running') %}
|
||||||
{% set vm_name = pillar.get('vm_name') %}
|
{% set vm_name = pillar.get('vm_name', '') %}
|
||||||
|
|
||||||
|
{% if not vm_name|regex_match('^([A-Za-z0-9._-]{1,253})$') %}
|
||||||
|
{% do salt.log.error('vm_pillar_clean_orch: refusing unsafe vm_name=' ~ vm_name) %}
|
||||||
|
vm_pillar_clean_invalid_name:
|
||||||
|
test.fail_without_changes:
|
||||||
|
- name: vm_pillar_clean_invalid_name
|
||||||
|
{% else %}
|
||||||
|
|
||||||
delete_adv_{{ vm_name }}_pillar:
|
delete_adv_{{ vm_name }}_pillar:
|
||||||
module.run:
|
module.run:
|
||||||
@@ -24,6 +31,8 @@ delete_{{ vm_name }}_pillar:
|
|||||||
- file.remove:
|
- file.remove:
|
||||||
- path: /opt/so/saltstack/local/pillar/minions/{{ vm_name }}.sls
|
- path: /opt/so/saltstack/local/pillar/minions/{{ vm_name }}.sls
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
{% do salt.log.error(
|
{% do salt.log.error(
|
||||||
|
|||||||
@@ -3,12 +3,15 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
{% if data['id'].endswith('_hypervisor') and data['result'] == True %}
|
{% set hid = data['id'] %}
|
||||||
|
{% if hid|regex_match('^([A-Za-z0-9._-]{1,253})$')
|
||||||
|
and hid.endswith('_hypervisor')
|
||||||
|
and data['result'] == True %}
|
||||||
|
|
||||||
{% if data['act'] == 'accept' %}
|
{% if data['act'] == 'accept' %}
|
||||||
check_and_trigger:
|
check_and_trigger:
|
||||||
runner.setup_hypervisor.setup_environment:
|
runner.setup_hypervisor.setup_environment:
|
||||||
- minion_id: {{ data['id'] }}
|
- minion_id: {{ hid }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if data['act'] == 'delete' %}
|
{% if data['act'] == 'delete' %}
|
||||||
@@ -17,8 +20,7 @@ delete_hypervisor:
|
|||||||
- args:
|
- args:
|
||||||
- mods: orch.delete_hypervisor
|
- mods: orch.delete_hypervisor
|
||||||
- pillar:
|
- pillar:
|
||||||
minion_id: {{ data['id'] }}
|
minion_id: {{ hid }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!py
|
#!py
|
||||||
|
|
||||||
# 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.
|
||||||
|
|
||||||
@@ -9,30 +9,42 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
import grp
|
import grp
|
||||||
|
import re
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PILLAR_ROOT = '/opt/so/saltstack/local/pillar/minions/'
|
||||||
|
_VMNAME_RE = re.compile(r'^[A-Za-z0-9._-]{1,253}$')
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
vm_name = data['kwargs']['name']
|
vm_name = data.get('kwargs', {}).get('name', '')
|
||||||
logging.error("createEmptyPillar reactor: vm_name: %s" % vm_name)
|
if not _VMNAME_RE.match(str(vm_name)):
|
||||||
pillar_root = '/opt/so/saltstack/local/pillar/minions/'
|
log.error("createEmptyPillar reactor: refusing unsafe vm_name=%r", vm_name)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
log.info("createEmptyPillar reactor: vm_name: %s", vm_name)
|
||||||
pillar_files = ['adv_' + vm_name + '.sls', vm_name + '.sls']
|
pillar_files = ['adv_' + vm_name + '.sls', vm_name + '.sls']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get socore user and group IDs
|
|
||||||
socore_uid = pwd.getpwnam('socore').pw_uid
|
socore_uid = pwd.getpwnam('socore').pw_uid
|
||||||
socore_gid = grp.getgrnam('socore').gr_gid
|
socore_gid = grp.getgrnam('socore').gr_gid
|
||||||
|
pillar_root_real = os.path.realpath(PILLAR_ROOT)
|
||||||
|
|
||||||
for f in pillar_files:
|
for f in pillar_files:
|
||||||
full_path = pillar_root + f
|
full_path = os.path.join(PILLAR_ROOT, f)
|
||||||
if not os.path.exists(full_path):
|
resolved = os.path.realpath(full_path)
|
||||||
# Create empty file
|
if os.path.dirname(resolved) != pillar_root_real:
|
||||||
os.mknod(full_path)
|
log.error("createEmptyPillar reactor: refusing path outside pillar root: %s", resolved)
|
||||||
# Set ownership to socore:socore
|
continue
|
||||||
os.chown(full_path, socore_uid, socore_gid)
|
if os.path.exists(resolved):
|
||||||
# Set mode to 644 (rw-r--r--)
|
continue
|
||||||
os.chmod(full_path, 0o640)
|
os.mknod(resolved)
|
||||||
logging.error("createEmptyPillar reactor: created %s with socore:socore ownership and mode 644" % f)
|
os.chown(resolved, socore_uid, socore_gid)
|
||||||
|
os.chmod(resolved, 0o640)
|
||||||
|
log.info("createEmptyPillar reactor: created %s with socore:socore ownership and mode 0640", f)
|
||||||
|
|
||||||
except (KeyError, OSError) as e:
|
except (KeyError, OSError) as e:
|
||||||
logging.error("createEmptyPillar reactor: Error setting ownership/permissions: %s" % str(e))
|
log.error("createEmptyPillar reactor: Error setting ownership/permissions: %s", e)
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
+33
-11
@@ -1,18 +1,40 @@
|
|||||||
|
#!py
|
||||||
|
|
||||||
# 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.
|
||||||
|
|
||||||
remove_key:
|
import logging
|
||||||
wheel.key.delete:
|
import re
|
||||||
- args:
|
|
||||||
- match: {{ data['name'] }}
|
|
||||||
|
|
||||||
{{ data['name'] }}_pillar_clean:
|
log = logging.getLogger(__name__)
|
||||||
runner.state.orchestrate:
|
|
||||||
- args:
|
|
||||||
- mods: orch.vm_pillar_clean
|
|
||||||
- pillar:
|
|
||||||
vm_name: {{ data['name'] }}
|
|
||||||
|
|
||||||
{% do salt.log.info('deleteKey reactor: deleted minion key: %s' % data['name']) %}
|
_VMNAME_RE = re.compile(r'^[A-Za-z0-9._-]{1,253}$')
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
name = data.get('name', '')
|
||||||
|
if not _VMNAME_RE.match(str(name)):
|
||||||
|
log.error("deleteKey reactor: refusing unsafe name=%r", name)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
log.info("deleteKey reactor: deleted minion key: %s", name)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'remove_key': {
|
||||||
|
'wheel.key.delete': [
|
||||||
|
{'args': [
|
||||||
|
{'match': name},
|
||||||
|
]},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'%s_pillar_clean' % name: {
|
||||||
|
'runner.state.orchestrate': [
|
||||||
|
{'args': [
|
||||||
|
{'mods': 'orch.vm_pillar_clean'},
|
||||||
|
{'pillar': {'vm_name': name}},
|
||||||
|
]},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user