aim-web2.1.0rc9

This commit is contained in:
admin_rb
2026-09-22 19:23:17 +02:00
parent d095887d2e
commit 3dfc80b782
438 changed files with 31613 additions and 1510 deletions
+23
View File
@@ -0,0 +1,23 @@
# checkmk_agent
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
checkmk_linux_tmp_path: /tmp
checkmk_windows_tmp_path: C:\Windows\Temp
checkmk_deb_filename: check-mk-agent.deb
checkmk_rpm_filename: check-mk-agent.rpm
checkmk_msi_filename: check_mk_agent.msi
checkmk_agent_files_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_AGENT_FILES_DIR'') | default(role_path
~ ''/files'', true) }}'
```
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
+8 -8
View File
@@ -1,9 +1,9 @@
---
checkmk_linux_tmp_path: "/tmp"
checkmk_windows_tmp_path: "C:\\Windows\\Temp"
checkmk_deb_filename: "check-mk-agent.deb"
checkmk_rpm_filename: "check-mk-agent.rpm"
checkmk_msi_filename: "check_mk_agent.msi"
checkmk_linux_socket_name: "check-mk-agent.socket"
checkmk_linux_service_name: "check-mk-agent"
checkmk_windows_service_name: "CheckMkService"
checkmk_linux_tmp_path: /tmp
checkmk_windows_tmp_path: C:\Windows\Temp
checkmk_deb_filename: check-mk-agent.deb
checkmk_rpm_filename: check-mk-agent.rpm
checkmk_msi_filename: check_mk_agent.msi
checkmk_agent_files_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_AGENT_FILES_DIR'') | default(role_path
~ ''/files'', true) }}'
+2 -4
View File
@@ -1,5 +1,3 @@
Place the Checkmk agent packages here:
# Staged agent packages
- `check-mk-agent.deb`
- `check-mk-agent.rpm`
- `check_mk_agent.msi`
AIM Maintenance populates `check_mk_agent.msi`, `check-mk-agent.deb` and `check-mk-agent.rpm` here by default. Binaries are not included or replaced by this source bundle. Existing package files must be retained.
-55
View File
@@ -1,55 +0,0 @@
---
- name: "Enable & start Checkmk socket (if present)"
listen: "checkmk | linux | agent-ensure-running"
when: ansible_facts['os_family'] != "Windows"
ansible.builtin.systemd:
name: "{{ checkmk_linux_socket_name }}"
enabled: true
state: started
daemon_reload: true
failed_when: false
- name: "Enable & start Checkmk service (fallback/if present)"
listen: "checkmk | linux | agent-ensure-running"
when: ansible_facts['os_family'] != "Windows"
ansible.builtin.systemd:
name: "{{ checkmk_linux_service_name }}"
enabled: true
state: started
daemon_reload: true
failed_when: false
- name: "Windows | Detect Checkmk service name"
listen: "checkmk | windows | agent-ensure-running"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_powershell:
script: |
$candidates = @('CheckMkService','Check_MK_Agent')
foreach ($n in $candidates) {
$svc = Get-Service -Name $n -ErrorAction SilentlyContinue
if ($svc) { $svc.Name; break }
}
register: cmk_detect
failed_when: false
- name: "Windows | Set detected service name"
listen: "checkmk | windows | agent-ensure-running"
when: ansible_facts['os_family'] == "Windows"
ansible.builtin.set_fact:
cmk_service_name: >-
{{
(cmk_detect.output[0] | default('') | trim)
if (cmk_detect.output | default([]) | length > 0)
else (checkmk_windows_service_name | default('CheckMkService'))
}}
- name: "Windows | Ensure Checkmk agent service running"
listen: "checkmk | windows | agent-ensure-running"
when:
- ansible_facts['os_family'] == "Windows"
- (cmk_service_name | default('')) | length > 0
ansible.windows.win_service:
name: "{{ cmk_service_name }}"
start_mode: auto
state: started
failed_when: false
-6
View File
@@ -1,6 +0,0 @@
---
galaxy_info:
role_name: checkmk_agent
description: Install Checkmk agent from local packages
min_ansible_version: "2.18"
dependencies: []
-11
View File
@@ -1,11 +0,0 @@
---
- name: "Debian | Copy Checkmk agent package"
ansible.builtin.copy:
src: "{{ checkmk_deb_filename }}"
dest: "{{ checkmk_linux_tmp_path }}/{{ checkmk_deb_filename }}"
mode: "0644"
- name: "Debian | Install Checkmk agent"
ansible.builtin.apt:
deb: "{{ checkmk_linux_tmp_path }}/{{ checkmk_deb_filename }}"
notify: "checkmk | linux | agent-ensure-running"
@@ -0,0 +1,25 @@
---
- name: Checkmk | Verify staged package on controller
ansible.builtin.stat:
path: '{{ checkmk_agent_files_dir }}/{{ checkmk_deb_filename }}'
delegate_to: localhost
become: false
register: _checkmk_package
- name: Checkmk | Require staged package
ansible.builtin.assert:
that:
- _checkmk_package.stat.isreg | default(false)
- _checkmk_package.stat.size | default(0) | int > 0
fail_msg: Required agent package is absent/empty. Use AIM Maintenance to download packages first.
quiet: true
- name: Debian | Copy Checkmk agent package from role files
ansible.builtin.copy:
src: '{{ checkmk_agent_files_dir }}/{{ checkmk_deb_filename }}'
dest: '{{ checkmk_linux_tmp_path }}/{{ checkmk_deb_filename }}'
mode: '0644'
- name: Debian | Install Checkmk agent from local .deb
ansible.builtin.apt:
deb: '{{ checkmk_linux_tmp_path }}/{{ checkmk_deb_filename }}'
state: present
register: _checkmk_package_install
@@ -0,0 +1,25 @@
---
- name: Checkmk | Verify staged package on controller
ansible.builtin.stat:
path: '{{ checkmk_agent_files_dir }}/{{ checkmk_rpm_filename }}'
delegate_to: localhost
become: false
register: _checkmk_package
- name: Checkmk | Require staged package
ansible.builtin.assert:
that:
- _checkmk_package.stat.isreg | default(false)
- _checkmk_package.stat.size | default(0) | int > 0
fail_msg: Required agent package is absent/empty. Use AIM Maintenance to download packages first.
quiet: true
- name: RedHat | Copy Checkmk agent package from role files
ansible.builtin.copy:
src: '{{ checkmk_agent_files_dir }}/{{ checkmk_rpm_filename }}'
dest: '{{ checkmk_linux_tmp_path }}/{{ checkmk_rpm_filename }}'
mode: '0644'
- name: RedHat | Install Checkmk agent from local .rpm
ansible.builtin.dnf:
name: '{{ checkmk_linux_tmp_path }}/{{ checkmk_rpm_filename }}'
state: present
register: _checkmk_package_install
+14 -9
View File
@@ -1,12 +1,17 @@
---
- name: Include Debian installation
ansible.builtin.include_tasks: debian.yml
when: ansible_facts['os_family'] == 'Debian'
- name: Include RedHat installation
ansible.builtin.include_tasks: redhat.yml
when: ansible_facts['os_family'] == 'RedHat'
- name: Include Windows installation
- name: Checkmk | Supported installer
ansible.builtin.assert:
that:
- ansible_facts.os_family in ['Debian','RedHat','Windows']
fail_msg: Unsupported installer platform. No Python/package-manager bootstrap is performed.
quiet: true
- name: Include Debian tasks
ansible.builtin.include_tasks: linux_debian.yml
when: ansible_facts['os_family'] == "Debian"
- name: Include RedHat tasks
ansible.builtin.include_tasks: linux_redhat.yml
when: ansible_facts['os_family'] == "RedHat"
- name: Include Windows tasks
ansible.builtin.include_tasks: windows.yml
when: ansible_facts['os_family'] == 'Windows'
when: ansible_facts['os_family'] == "Windows"
-12
View File
@@ -1,12 +0,0 @@
---
- name: "RedHat | Copy Checkmk agent package"
ansible.builtin.copy:
src: "{{ checkmk_rpm_filename }}"
dest: "{{ checkmk_linux_tmp_path }}/{{ checkmk_rpm_filename }}"
mode: "0644"
- name: "RedHat | Install Checkmk agent"
ansible.builtin.package:
name: "{{ checkmk_linux_tmp_path }}/{{ checkmk_rpm_filename }}"
state: present
notify: "checkmk | linux | agent-ensure-running"
+24 -7
View File
@@ -1,11 +1,28 @@
---
- name: "Windows | Copy Checkmk agent MSI"
ansible.windows.win_copy:
src: "{{ checkmk_msi_filename }}"
dest: "{{ checkmk_windows_tmp_path }}\\{{ checkmk_msi_filename }}"
- name: "Windows | Install Checkmk agent from local MSI"
- name: Checkmk | Verify staged package on controller
ansible.builtin.stat:
path: '{{ checkmk_agent_files_dir }}/{{ checkmk_msi_filename }}'
delegate_to: localhost
become: false
register: _checkmk_package
- name: Checkmk | Require staged package
ansible.builtin.assert:
that:
- _checkmk_package.stat.isreg | default(false)
- _checkmk_package.stat.size | default(0) | int > 0
fail_msg: Required agent package is absent/empty. Use AIM Maintenance to download packages first.
quiet: true
- name: Windows | Ensure temp dir exists
ansible.windows.win_file:
path: '{{ checkmk_windows_tmp_path }}'
state: directory
- name: Windows | Copy Checkmk agent MSI from role files
ansible.windows.win_copy:
src: '{{ checkmk_agent_files_dir }}/{{ checkmk_msi_filename }}'
dest: '{{ checkmk_windows_tmp_path }}\{{ checkmk_msi_filename }}'
- name: Windows | Install Checkmk agent from local MSI
ansible.windows.win_package:
path: "{{ checkmk_windows_tmp_path }}\\{{ checkmk_msi_filename }}"
path: '{{ checkmk_windows_tmp_path }}\{{ checkmk_msi_filename }}'
state: present
notify: "checkmk | windows | agent-ensure-running"
register: _checkmk_package_install
-6
View File
@@ -1,6 +0,0 @@
---
galaxy_info:
role_name: checkmk_agent_config
description: Render Windows Checkmk agent configuration from detected server roles
min_ansible_version: "2.18"
dependencies: []
-20
View File
@@ -1,20 +0,0 @@
---
- name: "Debug detected role flags"
when: ansible_facts['os_family'] == "Windows"
ansible.builtin.debug:
msg:
dc: "{{ is_dc | default(false) }}"
dhcp: "{{ is_dhcp_server | default(false) }}"
vbr: "{{ has_veeam_vbr | default(false) }}"
vbo: "{{ has_veeam_vbo | default(false) }}"
em: "{{ has_veeam_em | default(false) }}"
hv: "{{ is_hyperv_host | default(false) }}"
timeout_updates: "{{ checkmk_windows_updates_timeout }}"
- name: "Windows | Render check_mk.user.yml"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_template:
src: "windows_check_mk.user.yml.j2"
dest: "{{ checkmk_windows_user_cfg }}"
backup: true
notify: "checkmk | windows | agent-ensure-running"
@@ -1,130 +0,0 @@
# Managed by Ansible (checkmk_agent_config)
# Windows Checkmk Agent user configuration built from detected roles.
# $CUSTOM_PLUGINS_PATH$ -> ProgramData\checkmk\agent\plugins
# $BUILTIN_PLUGINS_PATH$ -> Program Files (x86)\checkmk\service\plugins
# $CUSTOM_AGENT_PATH$ -> ProgramData\checkmk\agent
# $CUSTOM_LOCAL_PATH$ -> ProgramData\checkmk\agent\local
global:
_only_from:
_realtime:
enabled: yes
timeout: 90
port: 6559
encrypted: no
passphrase: this is my password
run:
- mem
- df
- winperf_processor
winperf:
counters:
- MSExchangeTransport Queues: msx_queues
_logfiles:
enabled: no
fileinfo:
path: []
logwatch:
logfile: []
plugins:
execution:
# --- Built-in defaults ---
- pattern: '$BUILTIN_PLUGINS_PATH$\windows_updates.vbs'
run: yes
async: yes
timeout: {{ checkmk_windows_updates_timeout }}
cache_age: {{ checkmk_windows_updates_cache }}
retry_count: 0
- pattern: '$BUILTIN_PLUGINS_PATH$\mk_inventory.vbs'
run: yes
async: yes
timeout: {{ checkmk_mk_inventory_timeout }}
cache_age: 3600
- pattern: '$BUILTIN_PLUGINS_PATH$\mssql.vbs'
run: yes
timeout: {{ checkmk_plugins_default_timeout }}
{% if has_veeam_vbr | default(false) %}
# --- Veeam Backup & Replication ---
- pattern: '$BUILTIN_PLUGINS_PATH$\veeam_backup_status.ps1'
run: yes
async: yes
timeout: {{ checkmk_plugins_default_timeout }}
cache_age: {{ checkmk_plugins_default_cache }}
{% endif %}
{% if is_dc | default(false) %}
# --- Domain Controller ---
- pattern: '$BUILTIN_PLUGINS_PATH$\ad_replication.bat'
run: yes
timeout: {{ checkmk_plugins_default_timeout }}
{% endif %}
{% if is_dhcp_server | default(false) %}
# --- DHCP Server ---
- pattern: '$BUILTIN_PLUGINS_PATH$\win_dhcp_pools.bat'
run: yes
timeout: {{ checkmk_plugins_default_timeout }}
{% endif %}
# --- Generic patterns / precedence ---
- pattern: '$CUSTOM_PLUGINS_PATH$\*.ps1'
run: yes
async: yes
timeout: {{ checkmk_plugins_default_timeout }}
cache_age: {{ checkmk_plugins_default_cache }}
- pattern: '$CUSTOM_PLUGINS_PATH$\*.*'
run: yes
timeout: {{ checkmk_plugins_default_timeout }}
- pattern: '$BUILTIN_PLUGINS_PATH$\*.*'
run: no
timeout: {{ checkmk_plugins_default_timeout }}
- pattern: '*'
run: no
{% for p in (checkmk_extra_plugin_patterns | default([])) %}
- pattern: '{{ p.pattern }}'
{% if p.run is defined %}
run: {{ p.run | bool }}
{% endif %}
{% if p.async is defined %}
async: {{ p.async | bool }}
{% endif %}
{% if p.timeout is defined %}
timeout: {{ p.timeout }}
{% endif %}
{% if p.cache_age is defined %}
cache_age: {{ p.cache_age }}
{% endif %}
{% endfor %}
local:
_execution:
- pattern: '*.*'
run: yes
{% for l in (checkmk_extra_local_patterns | default([])) %}
- pattern: '{{ l.pattern }}'
{% if l.run is defined %}
run: {{ l.run | bool }}
{% endif %}
{% if l.async is defined %}
async: {{ l.async | bool }}
{% endif %}
{% if l.timeout is defined %}
timeout: {{ l.timeout }}
{% endif %}
{% endfor %}
mrpe:
config: []
+36
View File
@@ -0,0 +1,36 @@
# checkmk_cleanup_scripts
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
checkmk_linux_plugin_dir: /usr/lib/check_mk_agent/plugins
checkmk_linux_local_dir: /usr/lib/check_mk_agent/local
checkmk_linux_config_dir: /etc/check_mk
checkmk_windows_plugin_dir: C:\ProgramData\checkmk\agent\plugins
checkmk_windows_builtin_plugin_dir: C:\Program Files (x86)\checkmk\service\plugins
checkmk_windows_local_dir: C:\ProgramData\checkmk\agent\local
checkmk_monitoring_scripts_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_MONITORING_SCRIPTS_DIR'')
| default(''/etc/checkmk_monitoring_scripts'', true) }}'
checkmk_windows_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Windows'
checkmk_linux_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Linux'
checkmk_unifi_mode: auto
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
want_windows_nsp_mailqueue: false
want_windows_certificate: false
want_windows_veeam_cloud_connect: false
want_windows_veeam_backup: false
checkmk_cleanup_enabled: false
```
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -0,0 +1,22 @@
---
checkmk_linux_plugin_dir: /usr/lib/check_mk_agent/plugins
checkmk_linux_local_dir: /usr/lib/check_mk_agent/local
checkmk_linux_config_dir: /etc/check_mk
checkmk_windows_plugin_dir: C:\ProgramData\checkmk\agent\plugins
checkmk_windows_builtin_plugin_dir: C:\Program Files (x86)\checkmk\service\plugins
checkmk_windows_local_dir: C:\ProgramData\checkmk\agent\local
checkmk_monitoring_scripts_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_MONITORING_SCRIPTS_DIR'')
| default(''/etc/checkmk_monitoring_scripts'', true) }}'
checkmk_windows_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Windows'
checkmk_linux_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Linux'
checkmk_unifi_mode: auto
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
want_windows_nsp_mailqueue: false
want_windows_certificate: false
want_windows_veeam_cloud_connect: false
want_windows_veeam_backup: false
checkmk_cleanup_enabled: false
@@ -0,0 +1,15 @@
- name: Cleanup | Remove obsolete managed local check
ansible.builtin.file:
path: '{{ checkmk_linux_local_dir }}/{{ item }}'
state: absent
loop: '{{ _checkmk_remove_paths }}'
register: _aim_cleanup_files
- name: Cleanup | Remove UniFi configuration only when UniFi is disabled
ansible.builtin.file:
path: '{{ checkmk_linux_config_dir }}/unifi.cfg'
state: absent
when: _checkmk_unifi_effective == 'disabled'
diff: false
no_log: true
register: _aim_cleanup_unifi
@@ -0,0 +1,42 @@
- name: Cleanup | Validate opt-in
ansible.builtin.assert:
that:
- (checkmk_cleanup_enabled) is boolean or (checkmk_cleanup_enabled | string | lower) in ['true',
'false']
fail_msg: checkmk_cleanup_enabled must be boolean.
quiet: true
- name: Cleanup | Build obsolete paths
ansible.builtin.set_fact:
_checkmk_remove_paths: "{{ _checkmk_obsolete_scripts | map(attribute='filename') | list }}"
- name: Cleanup | Candidate files
ansible.builtin.debug:
msg:
directory: "{{ checkmk_windows_local_dir if ansible_facts.os_family == 'Windows' else checkmk_linux_local_dir
}}"
files: '{{ _checkmk_remove_paths }}'
unifi_config: "{{ 'remove only when disabled' if ansible_facts.os_family != 'Windows' and _checkmk_unifi_effective
== 'disabled' else 'retained' }}"
mode: "{{ 'DELETE APPROVED' if checkmk_cleanup_enabled | bool else 'PREVIEW ONLY' }}"
- name: Cleanup | linux
ansible.builtin.include_tasks: linux.yml
when:
- checkmk_cleanup_enabled | bool
- ansible_facts.os_family != 'Windows'
- name: Cleanup | windows
ansible.builtin.include_tasks: windows.yml
when:
- checkmk_cleanup_enabled | bool
- ansible_facts.os_family == 'Windows'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: managed_cleanup_preview_v1
data: "{{ _checkmk_remove_paths | aim_report_cleanup(checkmk_windows_local_dir if ansible_facts.os_family
== 'Windows' else checkmk_linux_local_dir, _aim_cleanup_files | default({}), _checkmk_unifi_effective
if ansible_facts.os_family != 'Windows' else 'not_applicable', _aim_cleanup_unifi | default({}), checkmk_cleanup_enabled
| bool, ansible_check_mode) }}"
@@ -0,0 +1,36 @@
---
- name: Cleanup | Remove obsolete managed local check or legacy local plugin copy
ansible.windows.win_file:
path: '{{ checkmk_windows_local_dir }}\{{ item }}'
state: absent
loop: '{{ _checkmk_remove_paths }}'
register: _aim_cleanup_local_files
- name: Cleanup | Remove obsolete managed custom plugin
ansible.windows.win_file:
path: '{{ checkmk_windows_plugin_dir }}\{{ item }}'
state: absent
loop: >-
{{ _checkmk_obsolete_scripts
| selectattr('destination', 'defined')
| selectattr('destination', 'equalto', 'custom_plugin')
| map(attribute='filename') | list }}
register: _aim_cleanup_custom_plugin_files
- name: Cleanup | Remove obsolete known legacy built-in plugin copy
ansible.windows.win_file:
path: '{{ checkmk_windows_builtin_plugin_dir }}\{{ item }}'
state: absent
loop: >-
{{ _checkmk_remove_paths
| select('in', ['veeam_o365_status.ps1', 'veeam_backup_status.ps1'])
| list }}
register: _aim_cleanup_builtin_files
- name: Cleanup | Combine Windows cleanup results
ansible.builtin.set_fact:
_aim_cleanup_files:
results: >-
{{ (_aim_cleanup_local_files.results | default([]))
+ (_aim_cleanup_custom_plugin_files.results | default([]))
+ (_aim_cleanup_builtin_files.results | default([])) }}
+33
View File
@@ -0,0 +1,33 @@
# checkmk_configure_agent
On Windows, AIM owns only the top-level `plugins:` section of `check_mk.user.yml`.
The role preserves all other top-level sections and comments, including `global`,
`winperf`, `fileinfo`, `logwatch`, `local`, and `mrpe`.
The first line is an AIM ownership notice. The managed `plugins:` section also gets
its own ownership comment so operators can see the exact management boundary.
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
checkmk_windows_user_cfg: C:\ProgramData\checkmk\agent\check_mk.user.yml
checkmk_windows_updates_timeout: 3600
checkmk_windows_updates_cache: 43200
checkmk_mk_inventory_timeout: 120
checkmk_plugins_default_timeout: 120
checkmk_plugins_default_cache: 600
checkmk_extra_plugin_patterns: []
```
`checkmk_extra_plugin_patterns` entries are inserted before AIM's standard plugin
rules. AIM does not manage `local:` or `mrpe:` from this role; existing host-specific
configuration in those sections is left intact.
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -1,9 +1,10 @@
---
checkmk_windows_user_cfg: "C:\\ProgramData\\checkmk\\agent\\check_mk.user.yml"
# AIM owns only the top-level plugins section in the Windows user configuration.
# All other sections and comments must remain untouched.
checkmk_windows_user_cfg: C:\ProgramData\checkmk\agent\check_mk.user.yml
checkmk_windows_updates_timeout: 3600
checkmk_windows_updates_cache: 43200
checkmk_mk_inventory_timeout: 120
checkmk_plugins_default_timeout: 120
checkmk_plugins_default_cache: 600
checkmk_extra_plugin_patterns: []
checkmk_extra_local_patterns: []
@@ -0,0 +1,196 @@
---
- name: Checkmk | Validate Windows plugin execution settings
ansible.builtin.assert:
that:
- checkmk_extra_plugin_patterns is sequence
- checkmk_extra_plugin_patterns is not string
- checkmk_windows_updates_timeout | int >= 0
- checkmk_windows_updates_cache | int >= 0
- checkmk_mk_inventory_timeout | int >= 0
- checkmk_plugins_default_timeout | int >= 0
- checkmk_plugins_default_cache | int >= 0
fail_msg: Invalid Checkmk plugin execution setting type or negative timeout.
quiet: true
when: ansible_facts.os_family == 'Windows'
- name: Checkmk | Validate custom plugin rule fields
ansible.builtin.assert:
that:
- item is mapping
- item.pattern is defined
- item.pattern is string
- item.run is not defined or item.run is boolean
- item['async'] is not defined or item['async'] is boolean
- item.timeout is not defined or item.timeout | int >= 0
- item.cache_age is not defined or item.cache_age | int >= 0
- item.keys() | difference(['pattern','run','async','timeout','cache_age','retry_count']) | length == 0
fail_msg: Custom plugin rules require pattern and supported execution fields.
quiet: true
loop: '{{ checkmk_extra_plugin_patterns }}'
loop_control:
label: custom plugin execution rule
no_log: true
when: ansible_facts.os_family == 'Windows'
- name: Windows | Render AIM-managed Checkmk plugins section
ansible.windows.win_template:
src: windows_plugins_section.yml.j2
dest: '{{ checkmk_windows_user_cfg }}.aim-plugins.tmp'
when: ansible_facts.os_family == 'Windows'
diff: false
changed_when: false
- name: Windows | Replace only Checkmk plugins section
ansible.windows.win_shell: |
$ErrorActionPreference = 'Stop'
$configPath = '{{ checkmk_windows_user_cfg }}'
$fragmentPath = '{{ checkmk_windows_user_cfg }}.aim-plugins.tmp'
$header = '# Managed by Ansible (checkmk_configure_agent). Only AIM-marked sections are modified; all other content is preserved.'
$legacyHeader = '# Managed by Ansible (checkmk_configure_agent).'
$managedMarkerPrefix = '# AIM managed section: plugins (checkmk_configure_agent).'
if (-not (Test-Path -LiteralPath $fragmentPath)) {
throw "AIM Checkmk plugins fragment is missing: $fragmentPath"
}
$fragment = [System.IO.File]::ReadAllText($fragmentPath)
$fragment = $fragment.TrimEnd([char[]]"`r`n")
if (Test-Path -LiteralPath $configPath) {
$original = [System.IO.File]::ReadAllText($configPath)
}
else {
$original = ''
}
if ($original.Contains("`r`n")) {
$newline = "`r`n"
}
else {
$newline = "`n"
}
$hadFinalNewline = $original.EndsWith("`r`n") -or $original.EndsWith("`n") -or $original.EndsWith("`r")
$lines = @()
if ($original.Length -gt 0) {
$lines = @([regex]::Split($original, "`r`n|`n|`r"))
if ($hadFinalNewline -and $lines.Count -gt 0 -and $lines[$lines.Count - 1] -eq '') {
if ($lines.Count -eq 1) {
$lines = @()
}
else {
$lines = @($lines[0..($lines.Count - 2)])
}
}
}
# Keep the AIM ownership notice as line 1 without discarding the previous first line.
if ($lines.Count -eq 0) {
$lines = @($header)
}
elseif ($lines[0] -eq $legacyHeader -or $lines[0].StartsWith('# Managed by Ansible (checkmk_configure_agent).')) {
$lines[0] = $header
}
else {
$lines = @($header) + $lines
}
$pluginIndex = -1
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^plugins\s*:\s*(?:#.*)?$') {
$pluginIndex = $i
break
}
}
$fragmentLines = @([regex]::Split($fragment, "`r`n|`n|`r"))
if ($pluginIndex -ge 0) {
$replaceStart = $pluginIndex
if ($pluginIndex -gt 0 -and $lines[$pluginIndex - 1].StartsWith($managedMarkerPrefix)) {
$replaceStart = $pluginIndex - 1
}
$nextTopLevelKey = $lines.Count
for ($i = $pluginIndex + 1; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^[A-Za-z_][A-Za-z0-9_.-]*\s*:') {
$nextTopLevelKey = $i
break
}
}
# Preserve blank lines and top-level comments immediately before the next untouched section.
$replaceEnd = $nextTopLevelKey
while ($replaceEnd -gt ($pluginIndex + 1)) {
$candidate = $lines[$replaceEnd - 1]
if ([string]::IsNullOrWhiteSpace($candidate) -or $candidate.StartsWith('#')) {
$replaceEnd--
}
else {
break
}
}
$before = @()
if ($replaceStart -gt 0) {
$before = @($lines[0..($replaceStart - 1)])
}
$after = @()
if ($replaceEnd -lt $lines.Count) {
$after = @($lines[$replaceEnd..($lines.Count - 1)])
}
$lines = @($before + $fragmentLines + $after)
}
else {
if ($lines.Count -gt 0 -and -not [string]::IsNullOrWhiteSpace($lines[$lines.Count - 1])) {
$lines += ''
}
$lines += $fragmentLines
}
$updated = [string]::Join($newline, $lines)
if ($hadFinalNewline -or $original.Length -eq 0) {
$updated += $newline
}
if ($updated -ne $original) {
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($configPath, $updated, $utf8NoBom)
Write-Output 'AIM_CHANGED=true'
}
else {
Write-Output 'AIM_CHANGED=false'
}
register: _checkmk_plugins_update
changed_when: "'AIM_CHANGED=true' in _checkmk_plugins_update.stdout"
when: ansible_facts.os_family == 'Windows'
notify: checkmk | windows | configuration-changed
diff: false
- name: Windows | Normalize ACL on Checkmk user configuration
ansible.builtin.include_role:
name: checkmk_windows_acl
vars:
checkmk_windows_acl_paths:
- '{{ checkmk_windows_user_cfg }}'
when: ansible_facts.os_family == 'Windows'
- name: Windows | Remove temporary Checkmk plugins fragment
ansible.windows.win_file:
path: '{{ checkmk_windows_user_cfg }}.aim-plugins.tmp'
state: absent
when: ansible_facts.os_family == 'Windows'
changed_when: false
- name: Checkmk | Configuration summary
ansible.builtin.debug:
msg:
destination: '{{ checkmk_windows_user_cfg }}'
managed_section: plugins
extra_plugin_rules: '{{ checkmk_extra_plugin_patterns | length }}'
other_sections: preserved
when:
- ansible_facts.os_family == 'Windows'
- aim_debug | default(false) | bool
@@ -0,0 +1,72 @@
# AIM managed section: plugins (checkmk_configure_agent). Content under plugins: may be replaced by AIM.
plugins:
execution:
{% if checkmk_extra_plugin_patterns | length %}
{{ checkmk_extra_plugin_patterns | to_nice_yaml(indent=2, sort_keys=false) | indent(4, true) }}
{% endif %}
- pattern: '$BUILTIN_PLUGINS_PATH$\windows_updates.vbs'
run: true
async: true
timeout: {{ checkmk_windows_updates_timeout | int }}
cache_age: {{ checkmk_windows_updates_cache | int }}
retry_count: 0
- pattern: '$BUILTIN_PLUGINS_PATH$\mk_inventory.vbs'
run: true
async: true
timeout: {{ checkmk_mk_inventory_timeout | int }}
cache_age: 3600
- pattern: '$BUILTIN_PLUGINS_PATH$\mssql.vbs'
run: true
timeout: {{ checkmk_plugins_default_timeout | int }}
{% if has_veeam_vbo | default(false) %}
- pattern: '$CUSTOM_PLUGINS_PATH$\veeam_o365_status.ps1'
run: true
async: true
timeout: {{ checkmk_plugins_default_timeout | int }}
cache_age: {{ checkmk_plugins_default_cache | int }}
{% endif %}
{% if want_windows_citrix | default(false) %}
- pattern: '$CUSTOM_PLUGINS_PATH$\citrix_sessions_customized.ps1'
run: true
async: true
timeout: {{ checkmk_plugins_default_timeout | int }}
cache_age: {{ checkmk_plugins_default_cache | int }}
{% endif %}
{% if want_windows_veeam_backup | default(false) %}
- pattern: '$CUSTOM_PLUGINS_PATH$\veeam_backup_status.ps1'
run: true
async: true
timeout: {{ checkmk_plugins_default_timeout | int }}
cache_age: {{ checkmk_plugins_default_cache | int }}
{% endif %}
{% if is_dc | default(false) %}
- pattern: '$BUILTIN_PLUGINS_PATH$\ad_replication.bat'
run: true
timeout: {{ checkmk_plugins_default_timeout | int }}
{% endif %}
{% if is_dhcp_server | default(false) %}
- pattern: '$BUILTIN_PLUGINS_PATH$\win_dhcp_pools.bat'
run: true
timeout: {{ checkmk_plugins_default_timeout | int }}
{% endif %}
{% if is_hyperv_host | default(false) %}
- pattern: '$BUILTIN_PLUGINS_PATH$\hyperv_vms.ps1'
run: true
timeout: {{ checkmk_plugins_default_timeout | int }}
- pattern: '$BUILTIN_PLUGINS_PATH$\hyperv_vms_guestinfos.ps1'
run: true
timeout: {{ checkmk_plugins_default_timeout | int }}
{% endif %}
- pattern: '$CUSTOM_PLUGINS_PATH$\*.ps1'
run: true
async: true
timeout: {{ checkmk_plugins_default_timeout | int }}
cache_age: {{ checkmk_plugins_default_cache | int }}
- pattern: '$CUSTOM_PLUGINS_PATH$\*.*'
run: true
timeout: {{ checkmk_plugins_default_timeout | int }}
- pattern: '$BUILTIN_PLUGINS_PATH$\*.*'
run: false
timeout: {{ checkmk_plugins_default_timeout | int }}
- pattern: '*'
run: false
+48
View File
@@ -0,0 +1,48 @@
# checkmk_deploy_scripts
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
# unifi.cfg is role-managed and replaced, mode 0600. Password comes from Vault.
# An absent/CHANGEME password fails before deployment; no credentials are logged.
checkmk_linux_plugin_dir: /usr/lib/check_mk_agent/plugins
checkmk_linux_local_dir: /usr/lib/check_mk_agent/local
checkmk_linux_config_dir: /etc/check_mk
checkmk_windows_plugin_dir: C:\ProgramData\checkmk\agent\plugins
checkmk_windows_builtin_plugin_dir: C:\Program Files (x86)\checkmk\service\plugins
checkmk_windows_local_dir: C:\ProgramData\checkmk\agent\local
checkmk_monitoring_scripts_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_MONITORING_SCRIPTS_DIR'')
| default(''/etc/checkmk_monitoring_scripts'', true) }}'
checkmk_windows_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Windows'
checkmk_linux_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Linux'
checkmk_unifi_mode: auto
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
want_windows_nsp_mailqueue: false
want_windows_certificate: false
want_windows_veeam_cloud_connect: false
want_windows_veeam_backup: false
checkmk_unifi_username: bf-monitoring
checkmk_unifi_password: '{{ vault_checkmk_unifi_password | default('''') }}'
checkmk_unifi_baseurl: '{{ ''https://127.0.0.1:11443'' if _checkmk_unifi_effective == ''os'' else ''https://127.0.0.1:8443''
}}'
checkmk_unifi_curl_options: ' --insecure --tlsv1.2'
checkmk_unifi_status_provisioning: 1
checkmk_unifi_status_upgrading: 1
checkmk_unifi_status_upgradable: 0
checkmk_unifi_status_heartbeat_missed: 1
checkmk_unifi_status_noautobackup: 0
```
`unifi.cfg` is generated from the supplied schema, POSIX-shell quoted, mode `0600`, and protected with `no_log` and `diff: false`. Use a Vault reference for the password. `CHANGEME` and empty passwords fail before deployment. The active UniFi mode replaces the alternative local check. Other obsolete scripts are removed only by explicit cleanup.
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -0,0 +1,32 @@
---
# unifi.cfg is role-managed and replaced, mode 0600. Password comes from Vault.
# An absent/CHANGEME password fails before deployment; no credentials are logged.
checkmk_linux_plugin_dir: /usr/lib/check_mk_agent/plugins
checkmk_linux_local_dir: /usr/lib/check_mk_agent/local
checkmk_linux_config_dir: /etc/check_mk
checkmk_windows_plugin_dir: C:\ProgramData\checkmk\agent\plugins
checkmk_windows_builtin_plugin_dir: C:\Program Files (x86)\checkmk\service\plugins
checkmk_windows_local_dir: C:\ProgramData\checkmk\agent\local
checkmk_monitoring_scripts_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_MONITORING_SCRIPTS_DIR'')
| default(''/etc/checkmk_monitoring_scripts'', true) }}'
checkmk_windows_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Windows'
checkmk_linux_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Linux'
checkmk_unifi_mode: auto
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
want_windows_nsp_mailqueue: false
want_windows_certificate: false
want_windows_veeam_cloud_connect: false
want_windows_veeam_backup: false
checkmk_unifi_username: bf-monitoring
checkmk_unifi_password: '{{ vault_checkmk_unifi_password | default('''') }}'
checkmk_unifi_baseurl: '{{ ''https://127.0.0.1:11443'' if _checkmk_unifi_effective == ''os'' else ''https://127.0.0.1:8443''
}}'
checkmk_unifi_curl_options: ' --insecure --tlsv1.2'
checkmk_unifi_status_provisioning: 1
checkmk_unifi_status_upgrading: 1
checkmk_unifi_status_upgradable: 0
checkmk_unifi_status_heartbeat_missed: 1
checkmk_unifi_status_noautobackup: 0
@@ -0,0 +1,40 @@
# UniFi mode replacement is the explicitly approved exception to separate cleanup.
# Unknown files and the active UniFi check are never removed here.
- name: Linux | Ensure local check directory
ansible.builtin.file:
path: '{{ checkmk_linux_local_dir }}'
state: directory
mode: '0755'
- name: Linux | Ensure configuration directory
ansible.builtin.file:
path: '{{ checkmk_linux_config_dir }}'
state: directory
mode: '0755'
- name: Linux | Write the single UniFi configuration
ansible.builtin.template:
src: unifi.cfg.j2
dest: '{{ checkmk_linux_config_dir }}/unifi.cfg'
owner: root
group: root
mode: '0600'
validate: /bin/sh -n %s
when: _checkmk_unifi_effective in ['network','os']
no_log: true
diff: false
register: _aim_unifi_write
- name: Linux | Deploy selected monitoring checks
ansible.builtin.copy:
src: '{{ item.source }}'
dest: '{{ checkmk_linux_local_dir }}/{{ item.filename }}'
mode: '0755'
loop: '{{ _checkmk_selected_scripts }}'
loop_control:
label: '{{ item.filename }}'
register: _aim_check_copies
- name: Linux | Remove only the opposite UniFi local check
ansible.builtin.file:
path: "{{ checkmk_linux_local_dir }}/{{ 'check_unifi-controller.sh' if _checkmk_unifi_effective == 'os' else
'check_unifi-os.sh' }}"
state: absent
when: _checkmk_unifi_effective in ['network','os']
register: _aim_opposite_remove
@@ -0,0 +1,10 @@
---
- name: Checkmk | Validate controller sources and required parameters
ansible.builtin.import_tasks: preflight.yml
- name: Checkmk | Deploy linux checks
ansible.builtin.include_tasks: linux.yml
when: ansible_facts.os_family != 'Windows'
- name: Checkmk | Deploy windows checks
ansible.builtin.include_tasks: windows.yml
when: ansible_facts.os_family == 'Windows'
@@ -0,0 +1,57 @@
---
- name: Checkmk | Inspect selected controller script sources
ansible.builtin.stat:
path: '{{ item.source }}'
delegate_to: localhost
become: false
loop: '{{ _checkmk_selected_scripts }}'
loop_control:
label: '{{ item.filename }}'
register: _checkmk_sources
- name: Checkmk | Require selected controller files
ansible.builtin.assert:
that:
- item.stat.exists | default(false)
- item.stat.isreg | default(false)
fail_msg: A selected monitoring script is missing on the controller. Sync the monitoring repository first.
quiet: true
loop: '{{ _checkmk_sources.results }}'
loop_control:
label: '{{ item.item.filename }}'
- name: Checkmk | Validate UniFi public settings
ansible.builtin.assert:
that:
- checkmk_unifi_username is string
- checkmk_unifi_username | length > 0
- checkmk_unifi_baseurl is match('^https?://[^\s]+$')
- checkmk_unifi_curl_options is string
- checkmk_unifi_status_provisioning | int in [0,1,2,3]
- checkmk_unifi_status_upgrading | int in [0,1,2,3]
- checkmk_unifi_status_upgradable | int in [0,1,2,3]
- checkmk_unifi_status_heartbeat_missed | int in [0,1,2,3]
- checkmk_unifi_status_noautobackup | int in [0,1,2,3]
fail_msg: Invalid UniFi username, base URL, curl options or status mapping.
quiet: true
when:
- ansible_facts.os_family != 'Windows'
- _checkmk_unifi_effective in ['network','os']
- name: Checkmk | Require a real UniFi monitoring password
when:
- ansible_facts.os_family != 'Windows'
- _checkmk_unifi_effective in ['network','os']
block:
- name: Checkmk | Validate secret
ansible.builtin.assert:
that:
- checkmk_unifi_password is string
- checkmk_unifi_password | length > 0
- checkmk_unifi_password != 'CHANGEME'
fail_msg: A real UniFi password is required.
quiet: true
no_log: true
rescue:
- name: Checkmk | Explain missing UniFi secret
ansible.builtin.fail:
msg: Set vault_checkmk_unifi_password in the customer Vault, or override checkmk_unifi_password with
a host-specific Vault reference. Empty values and CHANGEME are refused. No secret was logged.
@@ -0,0 +1,68 @@
---
- name: Windows | Ensure Checkmk local directory
ansible.windows.win_file:
path: '{{ checkmk_windows_local_dir }}'
state: directory
- name: Windows | Ensure Checkmk custom plugin directory
ansible.windows.win_file:
path: '{{ checkmk_windows_plugin_dir }}'
state: directory
when: >-
{{ _checkmk_selected_scripts
| selectattr('destination', 'defined')
| selectattr('destination', 'equalto', 'custom_plugin')
| list | length > 0 }}
- name: Windows | Deploy selected monitoring checks
ansible.windows.win_copy:
src: '{{ item.source }}'
dest: >-
{{ (checkmk_windows_plugin_dir
if item.destination | default('local') == 'custom_plugin'
else checkmk_windows_local_dir) }}\{{ item.filename }}
loop: '{{ _checkmk_selected_scripts }}'
loop_control:
label: '{{ item.filename }}'
register: _aim_check_copies
- name: Windows | Normalize ACL on AIM-managed monitoring checks
ansible.builtin.include_role:
name: checkmk_windows_acl
vars:
checkmk_windows_acl_paths:
- >-
{{ (checkmk_windows_plugin_dir
if checkmk_acl_script.destination | default('local') == 'custom_plugin'
else checkmk_windows_local_dir) }}\{{ checkmk_acl_script.filename }}
loop: '{{ _checkmk_selected_scripts }}'
loop_control:
loop_var: checkmk_acl_script
label: '{{ checkmk_acl_script.filename }}'
- name: Windows | Remove legacy local copies after custom plugin relocation
ansible.windows.win_file:
path: '{{ checkmk_windows_local_dir }}\{{ item.filename }}'
state: absent
loop: >-
{{ _checkmk_selected_scripts
| selectattr('destination', 'defined')
| selectattr('destination', 'equalto', 'custom_plugin')
| list }}
loop_control:
label: '{{ item.filename }}'
register: _aim_custom_plugin_legacy_local_remove
- name: Windows | Remove known legacy built-in copies after custom plugin relocation
ansible.windows.win_file:
path: '{{ checkmk_windows_builtin_plugin_dir }}\{{ item.filename }}'
state: absent
loop: >-
{{ _checkmk_selected_scripts
| selectattr('destination', 'defined')
| selectattr('destination', 'equalto', 'custom_plugin')
| selectattr('filename', 'in', ['veeam_o365_status.ps1', 'veeam_backup_status.ps1'])
| list }}
loop_control:
label: '{{ item.filename }}'
register: _aim_custom_plugin_legacy_builtin_remove
@@ -0,0 +1,13 @@
# Managed by Ansible - checkmk_deploy_scripts. One UniFi variant per host.
# Values are POSIX-shell quoted because the monitoring scripts source this file.
USERNAME={{ checkmk_unifi_username | quote }}
PASSWORD={{ checkmk_unifi_password | quote }}
BASEURL={{ checkmk_unifi_baseurl | quote }}
CURLOPTS={{ checkmk_unifi_curl_options | quote }}
# 0 OK, 1 WARN, 2 CRIT, 3 UNKNOWN
STATUS_PROVISIONING={{ checkmk_unifi_status_provisioning | int }}
STATUS_UPGRADING={{ checkmk_unifi_status_upgrading | int }}
STATUS_UPGRADABLE={{ checkmk_unifi_status_upgradable | int }}
STATUS_HEARTBEAT_MISSED={{ checkmk_unifi_status_heartbeat_missed | int }}
STATUS_NOAUTOBACKUP={{ checkmk_unifi_status_noautobackup | int }}
+23
View File
@@ -0,0 +1,23 @@
# checkmk_manage_service
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
checkmk_linux_service_name: cmk-agent-ctl-daemon.service
checkmk_linux_socket_name: check-mk-agent.socket
checkmk_windows_service_name: ''
checkmk_windows_service_candidates:
- Check_MK_Agent
- CheckmkService
- Checkmk Service
```
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -0,0 +1,9 @@
---
checkmk_linux_service_name: cmk-agent-ctl-daemon.service
checkmk_linux_socket_name: check-mk-agent.socket
checkmk_windows_service_name: ''
checkmk_windows_service_candidates:
- Check_MK_Agent
- CheckmkService
- Checkmk Service
@@ -0,0 +1,9 @@
---
- name: Checkmk | Restart changed Windows agent configuration
ansible.windows.win_service:
name: '{{ item }}'
state: restarted
listen: checkmk | windows | configuration-changed
loop: '{{ _checkmk_windows_services | default([]) }}'
when: ansible_facts.os_family == 'Windows'
@@ -0,0 +1,42 @@
---
- name: Linux | Require systemd service management
ansible.builtin.assert:
that:
- ansible_facts.service_mgr == 'systemd'
fail_msg: This Checkmk service policy requires systemd. No alternate service system is configured.
quiet: true
- name: Linux | Refresh systemd after package installation
ansible.builtin.systemd_service:
daemon_reload: true
when: _checkmk_package_install.changed | default(false) | bool
- name: Linux | Detect configured Checkmk units independently of running state
ansible.builtin.command:
argv:
- systemctl
- show
- --property=LoadState
- --value
- '{{ item }}'
loop:
- '{{ checkmk_linux_socket_name }}'
- '{{ checkmk_linux_service_name }}'
register: _checkmk_units
changed_when: false
failed_when: 'false'
check_mode: false
- name: Linux | Select the installed unit, preferring the socket
ansible.builtin.set_fact:
_checkmk_linux_units: '{{ _checkmk_units.results | selectattr(''stdout'', ''defined'') | selectattr(''stdout'',
''equalto'', ''loaded'') | map(attribute=''item'') | list }}'
- name: Linux | Require an installed Checkmk unit
ansible.builtin.assert:
that:
- _checkmk_linux_units | length > 0
fail_msg: No configured Checkmk socket/service unit was found. Verify installation and the unit names.
quiet: true
- name: Linux | Ensure Checkmk is enabled and running
ansible.builtin.systemd_service:
name: '{{ _checkmk_linux_units | first }}'
enabled: true
state: started
@@ -0,0 +1,8 @@
---
- name: Checkmk | Ensure agent service on linux
ansible.builtin.include_tasks: linux.yml
when: ansible_facts.os_family != 'Windows'
- name: Checkmk | Ensure agent service on windows
ansible.builtin.include_tasks: windows.yml
when: ansible_facts.os_family == 'Windows'
@@ -0,0 +1,24 @@
---
- name: Windows | Find installed Checkmk service
ansible.windows.win_service_info:
name: '{{ item }}'
loop: '{{ ([checkmk_windows_service_name] if checkmk_windows_service_name | length else checkmk_windows_service_candidates)
}}'
register: _checkmk_win_service_query
- name: Windows | Record service names
ansible.builtin.set_fact:
_checkmk_windows_services: '{{ _checkmk_win_service_query.results | selectattr(''services'', ''defined'')
| map(attribute=''services'') | flatten | map(attribute=''name'') | unique | list }}'
- name: Windows | Require installed Checkmk service
ansible.builtin.assert:
that:
- _checkmk_windows_services | length > 0
fail_msg: No Checkmk service was found. Check the installed package or set checkmk_windows_service_name.
quiet: true
- name: Windows | Ensure Checkmk service is running
ansible.windows.win_service:
name: '{{ item }}'
start_mode: auto
state: started
loop: '{{ _checkmk_windows_services }}'
+9
View File
@@ -0,0 +1,9 @@
# checkmk_report
Reporting-only helper for the Checkmk installation playbooks. Queries installed version
from Windows uninstall registry or Debian/RPM package database, and re-reads current
service/unit state. Does not install packages or restart/configure services. Unknown or
ambiguous versions are null, never inferred from the staged package filename.
The calling playbook publishes checkmk_agent_state_v1 via set_stats. See
[OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
+79
View File
@@ -0,0 +1,79 @@
- name: Checkmk | Collect managed change summary
ansible.builtin.set_fact:
_aim_checkmk_changes: '{{ _aim_check_copies | default({}) | aim_report_checkmk_changes(_checkmk_selected_scripts,
_checkmk_plugins_update | default({}), _aim_unifi_write | default({}), _aim_opposite_remove | default({}),
_checkmk_unifi_effective, ansible_check_mode) }}'
# No supported Windows package-inventory module exposes arbitrary installed MSI/registry products.
# Keep this bounded read-only registry query until an official module covers that data.
- name: Checkmk | Query Windows installed version
ansible.windows.win_shell: |
$ErrorActionPreference = 'Stop'
$roots = @('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*')
$products = @(Get-ItemProperty -Path $roots -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match '^(Check_MK|Checkmk|Check MK).*Agent' })
$versions = @($products | Select-Object -ExpandProperty DisplayVersion -Unique)
$version = $null
if ($versions.Count -eq 1) { $version = [string]$versions[0] }
@{ installed=($products.Count -gt 0); version=$version; version_source='registry' } | ConvertTo-Json -Compress
register: _aim_checkmk_version_raw
changed_when: false
check_mode: false
when: ansible_facts.os_family == 'Windows'
- name: Checkmk | Collect Linux package facts
ansible.builtin.package_facts:
manager: auto
when: ansible_facts.os_family != 'Windows'
- name: Checkmk | Record Linux installed package rows
ansible.builtin.set_fact:
_aim_checkmk_linux_package_rows: "{{ ansible_facts.packages.get('check-mk-agent', []) }}"
when: ansible_facts.os_family != 'Windows'
- name: Checkmk | Observe Windows service state
ansible.windows.win_service_info:
name: '{{ item }}'
loop: '{{ _checkmk_windows_services | default([]) }}'
register: _aim_checkmk_final_services
when: ansible_facts.os_family == 'Windows'
- name: Checkmk | Collect Linux service facts
ansible.builtin.service_facts:
when: ansible_facts.os_family != 'Windows'
- name: Checkmk | Observe Linux unit state
ansible.builtin.set_fact:
_aim_checkmk_unit_state: >-
{{ ansible_facts.services.get(_checkmk_linux_units | first,
{'name': _checkmk_linux_units | first, 'state': 'unknown'}) }}
when: ansible_facts.os_family != 'Windows'
- name: Checkmk | Build installed state report
ansible.builtin.set_fact:
_aim_checkmk_state: >-
{{
(
(_aim_checkmk_version_raw.stdout | from_json)
if ansible_facts.os_family == 'Windows'
else {
'installed': (_aim_checkmk_linux_package_rows | default([]) | length) > 0,
'version': (
(_aim_checkmk_linux_package_rows | first).version
if (_aim_checkmk_linux_package_rows | default([]) | length) == 1
else none
),
'version_source': 'package_facts'
}
)
| aim_report_checkmk_state(
(
_aim_checkmk_final_services.results
| selectattr('services', 'defined')
| map(attribute='services')
| flatten
) if ansible_facts.os_family == 'Windows' else [_aim_checkmk_unit_state],
_aim_checkmk_changes,
_checkmk_package_install.changed | default(false),
ansible_check_mode
)
}}
+27
View File
@@ -0,0 +1,27 @@
# checkmk_script_plan
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
# Shared deployment and cleanup paths/optional switches. No secrets.
checkmk_linux_plugin_dir: /usr/lib/check_mk_agent/plugins
checkmk_linux_local_dir: /usr/lib/check_mk_agent/local
checkmk_linux_config_dir: /etc/check_mk
checkmk_windows_plugin_dir: C:\ProgramData\checkmk\agent\plugins
checkmk_windows_builtin_plugin_dir: C:\Program Files (x86)\checkmk\service\plugins
checkmk_windows_local_dir: C:\ProgramData\checkmk\agent\local
checkmk_monitoring_scripts_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_MONITORING_SCRIPTS_DIR'')
| default(''/etc/checkmk_monitoring_scripts'', true) }}'
checkmk_windows_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Windows'
checkmk_linux_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Linux'
checkmk_unifi_mode: auto
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
want_windows_nsp_mailqueue: false
want_windows_certificate: false
want_windows_veeam_cloud_connect: false
want_windows_veeam_backup: false
```
@@ -0,0 +1,21 @@
---
# Shared deployment and cleanup paths/optional switches. No secrets.
checkmk_linux_plugin_dir: /usr/lib/check_mk_agent/plugins
checkmk_linux_local_dir: /usr/lib/check_mk_agent/local
checkmk_linux_config_dir: /etc/check_mk
checkmk_windows_plugin_dir: C:\ProgramData\checkmk\agent\plugins
checkmk_windows_builtin_plugin_dir: C:\Program Files (x86)\checkmk\service\plugins
checkmk_windows_local_dir: C:\ProgramData\checkmk\agent\local
checkmk_monitoring_scripts_dir: '{{ lookup(''ansible.builtin.env'', ''AIM_CHECKMK_MONITORING_SCRIPTS_DIR'')
| default(''/etc/checkmk_monitoring_scripts'', true) }}'
checkmk_windows_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Windows'
checkmk_linux_scripts_dir: '{{ checkmk_monitoring_scripts_dir }}/Scripts Linux'
checkmk_unifi_mode: auto
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
want_windows_nsp_mailqueue: false
want_windows_certificate: false
want_windows_veeam_cloud_connect: false
want_windows_veeam_backup: false
+27
View File
@@ -0,0 +1,27 @@
---
- name: Checkmk | Validate UniFi mode
ansible.builtin.assert:
that:
- checkmk_unifi_mode in ['auto','network','os','disabled']
fail_msg: UniFi mode must be auto, network, os or disabled.
quiet: true
- name: Checkmk | Resolve UniFi mode
ansible.builtin.set_fact:
_checkmk_unifi_effective: '{{ checkmk_unifi_mode if checkmk_unifi_mode != ''auto'' else (''os'' if is_unifi_os_server
| default(false) | bool else (''network'' if is_unifi_controller | default(false) | bool else ''disabled''))
}}'
- name: Checkmk | Build managed script plan
ansible.builtin.set_fact:
_checkmk_script_catalog: '{{ _checkmk_windows_catalog if ansible_facts.os_family == ''Windows'' else _checkmk_linux_catalog
}}'
- name: Checkmk | Resolve selected and obsolete checks
ansible.builtin.set_fact:
_checkmk_selected_scripts: '{{ _checkmk_script_catalog | selectattr(''enabled'') | list }}'
_checkmk_obsolete_scripts: '{{ _checkmk_script_catalog | rejectattr(''enabled'') | list }}'
- name: Checkmk | Selected check plan
ansible.builtin.debug:
msg:
files: '{{ _checkmk_selected_scripts | map(attribute=''filename'') | list }}'
unifi_mode: '{{ _checkmk_unifi_effective }}'
when: aim_debug | default(false) | bool
+49
View File
@@ -0,0 +1,49 @@
---
# Internal managed filenames. Repository scripts are not embedded or rewritten by AIM.
_checkmk_windows_catalog:
- filename: check-ping.ps1
source: '{{ checkmk_windows_scripts_dir }}/check-ping.ps1'
enabled: '{{ is_dc | default(false) | bool }}'
- filename: veeam_config_backup_status.ps1
source: '{{ checkmk_windows_scripts_dir }}/veeam_config_backup_status.ps1'
enabled: '{{ has_veeam_vbr | default(false) | bool }}'
- filename: veeam_backup_license_status.ps1
source: '{{ checkmk_windows_scripts_dir }}/veeam_backup_license_status.ps1'
enabled: '{{ has_veeam_vbr | default(false) | bool }}'
- filename: veeam_o365_status.ps1
source: '{{ checkmk_windows_scripts_dir }}/veeam_o365_status.ps1'
destination: custom_plugin
enabled: '{{ has_veeam_vbo | default(false) | bool }}'
- filename: citrix_sessions_customized.ps1
source: '{{ checkmk_windows_scripts_dir }}/citrix_sessions_customized.ps1'
destination: custom_plugin
enabled: '{{ want_windows_citrix | default(false) | bool }}'
- filename: veeam_surebackup_status.ps1
source: '{{ checkmk_windows_scripts_dir }}/veeam_surebackup_status.ps1'
enabled: '{{ want_windows_surebackup | default(false) | bool }}'
- filename: windows-backup.ps1
source: '{{ checkmk_windows_scripts_dir }}/windows-backup.ps1'
enabled: '{{ want_windows_backup | default(false) | bool }}'
- filename: check-nsp-mailqueue.ps1
source: '{{ checkmk_windows_scripts_dir }}/check-nsp-mailqueue.ps1'
enabled: '{{ want_windows_nsp_mailqueue | default(false) | bool }}'
- filename: win_check_cert.ps1
source: '{{ checkmk_windows_scripts_dir }}/win_check_cert.ps1'
enabled: '{{ want_windows_certificate | default(false) | bool }}'
- filename: veeam_cloud_connect_status.ps1
source: '{{ checkmk_windows_scripts_dir }}/veeam_cloud_connect_status.ps1'
enabled: '{{ want_windows_veeam_cloud_connect | default(false) | bool }}'
- filename: veeam_backup_status.ps1
source: '{{ checkmk_windows_scripts_dir }}/veeam_backup_status.ps1'
destination: custom_plugin
enabled: '{{ want_windows_veeam_backup | default(false) | bool }}'
_checkmk_linux_catalog:
- filename: check_unifi-controller.sh
source: '{{ checkmk_linux_scripts_dir }}/check_unifi-controller/check_unifi-controller.sh'
enabled: '{{ _checkmk_unifi_effective == ''network'' }}'
- filename: check_unifi-os.sh
source: '{{ checkmk_linux_scripts_dir }}/check_unifi-controller/check_unifi-os.sh'
enabled: '{{ _checkmk_unifi_effective == ''os'' }}'
- filename: check_certificate_directory.sh
source: '{{ checkmk_linux_scripts_dir }}/check_certificate_directory.sh'
enabled: '{{ want_linux_check_certificate | default(false) | bool }}'
-12
View File
@@ -1,12 +0,0 @@
---
checkmk_linux_local_dir: "/usr/lib/check_mk_agent/local"
checkmk_linux_config_dir: "/etc/check_mk"
checkmk_windows_local_dir: "C:\\ProgramData\\checkmk\\agent\\local"
checkmk_linux_scripts_dir: "Linux/local"
checkmk_windows_scripts_dir: "Windows/local"
# Optional checks, disabled until explicitly requested
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
-16
View File
@@ -1,16 +0,0 @@
Place the actual monitoring scripts in these directories.
Linux/local/
- check_certificate_directory.sh
- check_unifi-controller.sh
- unifi.cfg
Windows/local/
- check-ping.ps1
- citrix_sessions_customized.ps1
- veeam_config_backup_status.ps1
- veeam_o365_status.ps1
- veeam_surebackup_status.ps1
- windows-backup.ps1
The ZIP intentionally does not invent script contents that were not provided.
-6
View File
@@ -1,6 +0,0 @@
---
galaxy_info:
role_name: checkmk_scripts
description: Deploy role-specific Checkmk local monitoring scripts
min_ansible_version: "2.18"
dependencies: []
-36
View File
@@ -1,36 +0,0 @@
---
- name: "Linux | Ensure local dir exists"
ansible.builtin.file:
path: "{{ checkmk_linux_local_dir }}"
state: directory
mode: "0755"
- name: "Linux | Ensure config dir exists"
ansible.builtin.file:
path: "{{ checkmk_linux_config_dir }}"
state: directory
mode: "0755"
- name: "Linux | Deploy UniFi local check"
when: is_unifi_controller | default(false) | bool
ansible.builtin.copy:
src: "{{ checkmk_linux_scripts_dir }}/check_unifi-controller.sh"
dest: "{{ checkmk_linux_local_dir }}/check_unifi-controller.sh"
mode: "0755"
notify: "checkmk | linux | agent-ensure-running"
- name: "Linux | Deploy unifi.cfg"
when: is_unifi_controller | default(false) | bool
ansible.builtin.copy:
src: "{{ checkmk_linux_scripts_dir }}/unifi.cfg"
dest: "{{ checkmk_linux_config_dir }}/unifi.cfg"
mode: "0644"
notify: "checkmk | linux | agent-ensure-running"
- name: "Linux | Deploy certificate directory check"
when: want_linux_check_certificate | default(false) | bool
ansible.builtin.copy:
src: "{{ checkmk_linux_scripts_dir }}/check_certificate_directory.sh"
dest: "{{ checkmk_linux_local_dir }}/check_certificate_directory.sh"
mode: "0755"
notify: "checkmk | linux | agent-ensure-running"
-8
View File
@@ -1,8 +0,0 @@
---
- name: Include Linux monitoring scripts
ansible.builtin.include_tasks: linux.yml
when: ansible_facts['os_family'] != 'Windows'
- name: Include Windows monitoring scripts
ansible.builtin.include_tasks: windows.yml
when: ansible_facts['os_family'] == 'Windows'
-47
View File
@@ -1,47 +0,0 @@
---
- name: "Windows | Ensure local dir exists"
ansible.windows.win_file:
path: "{{ checkmk_windows_local_dir }}"
state: directory
- name: "Windows | Deploy check-ping.ps1 (DC only)"
when: is_dc | default(false) | bool
ansible.windows.win_copy:
src: "{{ checkmk_windows_scripts_dir }}/check-ping.ps1"
dest: "{{ checkmk_windows_local_dir }}\\check-ping.ps1"
notify: "checkmk | windows | agent-ensure-running"
- name: "Windows | Deploy Veeam configuration backup status check (VBR only)"
when: has_veeam_vbr | default(false) | bool
ansible.windows.win_copy:
src: "{{ checkmk_windows_scripts_dir }}/veeam_config_backup_status.ps1"
dest: "{{ checkmk_windows_local_dir }}\\veeam_config_backup_status.ps1"
notify: "checkmk | windows | agent-ensure-running"
- name: "Windows | Deploy veeam_o365_status.ps1 (VBO only)"
when: has_veeam_vbo | default(false) | bool
ansible.windows.win_copy:
src: "{{ checkmk_windows_scripts_dir }}/veeam_o365_status.ps1"
dest: "{{ checkmk_windows_local_dir }}\\veeam_o365_status.ps1"
notify: "checkmk | windows | agent-ensure-running"
- name: "Windows | Deploy Citrix sessions check"
when: want_windows_citrix | default(false) | bool
ansible.windows.win_copy:
src: "{{ checkmk_windows_scripts_dir }}/citrix_sessions_customized.ps1"
dest: "{{ checkmk_windows_local_dir }}\\citrix_sessions_customized.ps1"
notify: "checkmk | windows | agent-ensure-running"
- name: "Windows | Deploy Veeam SureBackup check"
when: want_windows_surebackup | default(false) | bool
ansible.windows.win_copy:
src: "{{ checkmk_windows_scripts_dir }}/veeam_surebackup_status.ps1"
dest: "{{ checkmk_windows_local_dir }}\\veeam_surebackup_status.ps1"
notify: "checkmk | windows | agent-ensure-running"
- name: "Windows | Deploy Windows Backup check"
when: want_windows_backup | default(false) | bool
ansible.windows.win_copy:
src: "{{ checkmk_windows_scripts_dir }}/windows-backup.ps1"
dest: "{{ checkmk_windows_local_dir }}\\windows-backup.ps1"
notify: "checkmk | windows | agent-ensure-running"
+16
View File
@@ -0,0 +1,16 @@
# checkmk_windows_acl
Normalizes access on AIM-managed persistent Windows Checkmk files without recursively
changing Checkmk directories or unknown/operator files.
The role enables parent ACL inheritance and guarantees locale-independent well-known
principals by SID:
- SYSTEM (`S-1-5-18`): FullControl
- local Administrators (`S-1-5-32-544`): FullControl
- ALL APPLICATION PACKAGES (`S-1-15-2-1`): ReadAndExecute
- ALL RESTRICTED APPLICATION PACKAGES (`S-1-15-2-2`): ReadAndExecute
AIM does not add customer-specific administrator/user ACEs. Existing intentional parent
or explicit ACEs are not blindly purged. Pass persistent AIM-owned file paths through
`checkmk_windows_acl_paths`.
@@ -0,0 +1,15 @@
---
# Locale-independent well-known SIDs used by the native Checkmk Windows tree.
checkmk_windows_managed_acl_entries:
- sid: S-1-5-18
rights: FullControl
description: SYSTEM
- sid: S-1-5-32-544
rights: FullControl
description: Local Administrators
- sid: S-1-15-2-1
rights: ReadAndExecute
description: ALL APPLICATION PACKAGES
- sid: S-1-15-2-2
rights: ReadAndExecute
description: ALL RESTRICTED APPLICATION PACKAGES
+30
View File
@@ -0,0 +1,30 @@
---
- name: Windows ACL | Validate managed paths
ansible.builtin.assert:
that:
- checkmk_windows_acl_paths is defined
- checkmk_windows_acl_paths is sequence
- checkmk_windows_acl_paths is not string
- checkmk_windows_acl_paths | length > 0
fail_msg: checkmk_windows_acl_paths must contain one or more AIM-managed Windows files.
quiet: true
- name: Windows ACL | Ensure managed files inherit parent permissions
ansible.windows.win_acl_inheritance:
path: '{{ item }}'
state: present
reorganize: true
loop: '{{ checkmk_windows_acl_paths }}'
loop_control:
label: '{{ item }}'
- name: Windows ACL | Ensure Checkmk-style administrative and application access
ansible.windows.win_acl:
path: '{{ item.0 }}'
user: '{{ item.1.sid }}'
rights: '{{ item.1.rights }}'
type: allow
state: present
loop: '{{ checkmk_windows_acl_paths | product(checkmk_windows_managed_acl_entries) | list }}'
loop_control:
label: '{{ item.0 }} | {{ item.1.description }}'
@@ -0,0 +1,23 @@
# maintenance_export_event_logs
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
event_age_days: 45
export_folder: C:\Logs
event_log_channels:
- Application
- Security
- System
- Setup
```
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -0,0 +1,9 @@
---
event_age_days: 45
export_folder: C:\Logs
event_log_channels:
- Application
- Security
- System
- Setup
@@ -0,0 +1,63 @@
- name: Event logs | Validate input
ansible.builtin.assert:
that:
- event_age_days | int > 0
- event_age_days | int <= 36500
- export_folder is string
- export_folder | length > 0
- event_log_channels is sequence
- event_log_channels is not string
- event_log_channels | length > 0
fail_msg: Supply a positive age, a target folder and at least one event channel.
quiet: true
- name: Event logs | Ensure export directory
ansible.windows.win_file:
path: '{{ export_folder }}'
state: directory
- name: Event logs | Export selected channels
ansible.windows.win_powershell:
script: |
[CmdletBinding(SupportsShouldProcess)]
param([int]$EventAgeDays, [string]$ExportFolder, [string[]]$Channels)
$ErrorActionPreference = 'Stop'
$Ansible.Changed = $false
$date = Get-Date -Format 'yyyy-MM-dd_HHmmss'
$maxAgeMs = [int64]([timespan]::FromDays($EventAgeDays).TotalMilliseconds)
$q = "*[System[TimeCreated[timediff(@SystemTime) <= $maxAgeMs]]]"
$map = @{ Application='APP'; Security='SEC'; System='SYS'; Setup='INS' }
$files = @()
foreach ($log in $Channels) {
$suffix = if ($map.ContainsKey($log)) { $map[$log] } else { $log -replace '[^A-Za-z0-9_.-]', '_' }
$filename = Join-Path $ExportFolder "$date-$suffix.evtx"
if ($PSCmdlet.ShouldProcess($filename, "Export $log")) {
& wevtutil.exe epl $log $filename "/q:$q" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "Event export failed for channel '$log'. Exit: $LASTEXITCODE" }
if (-not (Test-Path -LiteralPath $filename)) { throw "Event export file is missing: $filename" }
$Ansible.Changed = $true
}
$files += $filename
}
$Ansible.Result = @{ files=$files; channels=$Channels; days=$EventAgeDays }
parameters:
EventAgeDays: '{{ event_age_days | int }}'
ExportFolder: '{{ export_folder }}'
Channels: '{{ event_log_channels }}'
error_action: stop
register: _aim_event_exports
- name: Event logs | Export summary
ansible.builtin.debug:
msg: '{{ _aim_event_exports.result }}'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: event_log_export_v1
data:
mode: "{{ 'check' if ansible_check_mode else 'apply' }}"
days: '{{ event_age_days | int }}'
channels: '{{ event_log_channels }}'
files: '{{ [] if ansible_check_mode else _aim_event_exports.result.files | default([]) }}'
+48
View File
@@ -0,0 +1,48 @@
# maintenance_patch_os
Operator defaults are intentionally low-precedence; inventory and explicit run options
may override them.
```yaml
---
os_patching_reboot: true
os_patching_windows_categories:
- SecurityUpdates
- CriticalUpdates
- UpdateRollups
- DefinitionUpdates
- Updates
os_patching_reboot_timeout: 600
os_patching_reboot_delay_minutes: 0
os_patching_reboot_message: 'AIM maintenance: operating system patching requires a reboot.'
os_patching_rescan_after_reboot: false
```
`os_patching_reboot_delay_minutes` is shared across Windows/Linux so the public setting
has one meaning. Linux reboot scheduling is minute-granular. Windows converts the value
to seconds; a zero-minute reboot still observes the Windows reboot module's minimum delay.
The message is displayed by the native reboot module when AIM actually initiates a reboot.
When automatic reboot is disabled, newly installed updates can legitimately leave
`reboot_deferred: true` while the patch run itself succeeds. A later run that detects the
already-pending reboot fails before starting new patch work and tells the operator to
reboot manually or enable the reboot option.
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
Runbook-owned filters normalize only reviewed fields; arbitrary package-manager/module
results are not exported.
## Windows patch waves
Windows uses the native `ansible.windows.win_updates` batch/orchestration path for the
currently selected categories. AIM calls it with `reboot: false`, so Windows Update may
process all updates in that current wave while AIM retains control over the reviewed reboot
message, delay and continuation policy. AIM does not create a per-update install queue.
The default `os_patching_rescan_after_reboot: false` stops the run after any AIM-performed
reboot boundary; a new operator-approved run discovers the next wave. Set it to true only
when the operator explicitly wants AIM to start another wave after reboot. A deferred reboot
always stops the run.
@@ -0,0 +1,16 @@
---
# Operator defaults. Existing os_patching_* variable names are intentionally retained.
os_patching_reboot: true
os_patching_windows_categories:
- SecurityUpdates
- CriticalUpdates
- UpdateRollups
- DefinitionUpdates
- Updates
os_patching_reboot_timeout: 600
# Cross-platform delay before an AIM-initiated reboot. Linux reboot scheduling is
# minute-granular, so this public setting is intentionally expressed in minutes.
os_patching_reboot_delay_minutes: 0
os_patching_reboot_message: 'AIM maintenance: operating system patching requires a reboot.'
# Windows only. False preserves one operator-approved patch wave per run.
os_patching_rescan_after_reboot: false
@@ -0,0 +1,144 @@
- name: Patching | Initialize Debian report state
ansible.builtin.set_fact:
_aim_patch_action_failed: false
_aim_patch_pre_reboot_performed: false
_aim_patch_post_reboot_performed: false
- name: Patching | Detect pending Debian reboot before patching
become: true
ansible.builtin.stat:
path: /var/run/reboot-required
register: _aim_patch_pre_reboot_probe
- name: Patching | Record pre-existing Debian reboot state
ansible.builtin.set_fact:
_aim_patch_preexisting_reboot_required: '{{ _aim_patch_pre_reboot_probe.stat.exists | default(false) | bool }}'
- name: Patching | Publish blocked Debian result when reboot is deferred
when:
- _aim_patch_preexisting_reboot_required | bool
- not (os_patching_reboot | bool)
block:
- name: Patching | Build blocked Debian patch report
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ 'debian' | aim_report_patch_blocked(ansible_check_mode,
os_patching_reboot_delay_minutes | int) }}
- name: AIM | Publish blocked operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Require reboot before continuing Debian patching
ansible.builtin.fail:
msg: >-
A reboot is already pending from a previous update or installation. Reboot the host first,
or rerun with "Reboot when required" enabled. No new package upgrade was started by this run.
- name: Patching | Clear pre-existing Debian reboot before patching
become: true
ansible.builtin.reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ (os_patching_reboot_delay_minutes | int) * 60 }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_pre_reboot
when:
- _aim_patch_preexisting_reboot_required | bool
- os_patching_reboot | bool
- not ansible_check_mode
- name: Patching | Record pre-patch Debian reboot
ansible.builtin.set_fact:
_aim_patch_pre_reboot_performed: '{{ _aim_patch_pre_reboot.rebooted | default(false) | bool }}'
- name: Patching | Collect installed package facts before operation
ansible.builtin.package_facts:
manager: auto
- name: Patching | Snapshot installed package facts before operation
ansible.builtin.set_fact:
_aim_packages_before: '{{ ansible_facts.packages | default({}) }}'
- name: Patching | Apply native Debian updates
block:
- name: Update Debian-based host
become: true
ansible.builtin.apt:
upgrade: safe
update_cache: true
cache_valid_time: 3600
autoremove: true
- name: Check if Debian-based host requires reboot
become: true
ansible.builtin.stat:
path: /var/run/reboot-required
register: os_patching_reboot_required
rescue:
- name: Patching | Retain failed action for reporting
ansible.builtin.set_fact:
_aim_patch_action_failed: true
- name: Patching | Reboot Debian host after updates when required
become: true
ansible.builtin.reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ (os_patching_reboot_delay_minutes | int) * 60 }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_post_reboot
when:
- os_patching_reboot | bool
- not ansible_check_mode
- os_patching_reboot_required.stat.exists | default(false) | bool
- name: Patching | Record post-update Debian reboot
ansible.builtin.set_fact:
_aim_patch_post_reboot_performed: '{{ _aim_patch_post_reboot.rebooted | default(false) | bool }}'
- name: Patching | Collect installed package facts after operation
ansible.builtin.package_facts:
manager: auto
- name: Patching | Snapshot installed package facts after operation
ansible.builtin.set_fact:
_aim_packages_after: '{{ ansible_facts.packages | default({}) }}'
- name: Patching | Compare package database snapshots
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ _aim_packages_before |
aim_report_patch_linux(
_aim_packages_after,
'debian',
ansible_check_mode,
not _aim_patch_action_failed,
os_patching_reboot_required.stat.exists | default(none),
(_aim_patch_pre_reboot_performed | bool) or (_aim_patch_post_reboot_performed | bool),
_aim_patch_preexisting_reboot_required | bool,
os_patching_reboot | bool,
os_patching_reboot_delay_minutes | int
) }}
- name: Patching | Package change summary
ansible.builtin.debug:
msg: '{{ _aim_patch_report }}'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Preserve native operation failure
ansible.builtin.fail:
msg: >-
The native Debian patch operation failed. Available observed package changes and reboot state
are in the structured result. If a reboot is reported as required, reboot before retrying.
when: _aim_patch_action_failed | bool
@@ -0,0 +1,167 @@
- name: Patching | Initialize RedHat report state
ansible.builtin.set_fact:
_aim_patch_action_failed: false
_aim_patch_pre_reboot_performed: false
_aim_patch_post_reboot_performed: false
_aim_patch_preexisting_reboot_required: false
- name: Patching | Detect existing needs-restarting command
ansible.builtin.command:
argv:
- /bin/sh
- -c
- command -v needs-restarting
register: _aim_needs_restarting_available
changed_when: false
failed_when: false
check_mode: false
- name: Patching | Detect pending RedHat reboot before patching
become: true
ansible.builtin.command:
cmd: needs-restarting -r
register: _aim_patch_pre_reboot_probe
changed_when: false
failed_when: _aim_patch_pre_reboot_probe.rc not in [0, 1]
when: _aim_needs_restarting_available.rc == 0
- name: Patching | Record pre-existing RedHat reboot state
ansible.builtin.set_fact:
_aim_patch_preexisting_reboot_required: >-
{{ (_aim_needs_restarting_available.rc == 0) and
(_aim_patch_pre_reboot_probe.rc | default(0) == 1) }}
- name: Patching | Publish blocked RedHat result when reboot is deferred
when:
- _aim_patch_preexisting_reboot_required | bool
- not (os_patching_reboot | bool)
block:
- name: Patching | Build blocked RedHat patch report
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ 'redhat' | aim_report_patch_blocked(ansible_check_mode,
os_patching_reboot_delay_minutes | int) }}
- name: AIM | Publish blocked operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Require reboot before continuing RedHat patching
ansible.builtin.fail:
msg: >-
A reboot is already pending from a previous update or installation. Reboot the host first,
or rerun with "Reboot when required" enabled. No new package upgrade was started by this run.
- name: Patching | Clear pre-existing RedHat reboot before patching
become: true
ansible.builtin.reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ (os_patching_reboot_delay_minutes | int) * 60 }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_pre_reboot
when:
- _aim_patch_preexisting_reboot_required | bool
- os_patching_reboot | bool
- not ansible_check_mode
- name: Patching | Record pre-patch RedHat reboot
ansible.builtin.set_fact:
_aim_patch_pre_reboot_performed: '{{ _aim_patch_pre_reboot.rebooted | default(false) | bool }}'
- name: Patching | Collect installed package facts before operation
ansible.builtin.package_facts:
manager: auto
- name: Patching | Snapshot installed package facts before operation
ansible.builtin.set_fact:
_aim_packages_before: '{{ ansible_facts.packages | default({}) }}'
- name: Patching | Apply native RedHat updates
block:
- name: Update RHEL-based host
become: true
ansible.builtin.dnf:
name: '*'
state: latest
update_only: true
- name: Ensure needs-restarting binary is present (yum-utils)
become: true
ansible.builtin.dnf:
name: yum-utils
state: present
- name: Check if RHEL-based host requires reboot
become: true
ansible.builtin.command:
cmd: needs-restarting -r
register: os_patching_reboot_required
changed_when: false
failed_when: os_patching_reboot_required.rc not in [0, 1]
rescue:
- name: Patching | Retain failed action for reporting
ansible.builtin.set_fact:
_aim_patch_action_failed: true
- name: Patching | Reboot RedHat host after updates when required
become: true
ansible.builtin.reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ (os_patching_reboot_delay_minutes | int) * 60 }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_post_reboot
when:
- os_patching_reboot | bool
- not ansible_check_mode
- os_patching_reboot_required.rc | default(0) == 1
- name: Patching | Record post-update RedHat reboot
ansible.builtin.set_fact:
_aim_patch_post_reboot_performed: '{{ _aim_patch_post_reboot.rebooted | default(false) | bool }}'
- name: Patching | Collect installed package facts after operation
ansible.builtin.package_facts:
manager: auto
- name: Patching | Snapshot installed package facts after operation
ansible.builtin.set_fact:
_aim_packages_after: '{{ ansible_facts.packages | default({}) }}'
- name: Patching | Compare package database snapshots
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ _aim_packages_before |
aim_report_patch_linux(
_aim_packages_after,
'redhat',
ansible_check_mode,
not _aim_patch_action_failed,
(os_patching_reboot_required.rc == 1) if os_patching_reboot_required.rc is defined else none,
(_aim_patch_pre_reboot_performed | bool) or (_aim_patch_post_reboot_performed | bool),
_aim_patch_preexisting_reboot_required | bool,
os_patching_reboot | bool,
os_patching_reboot_delay_minutes | int
) }}
- name: Patching | Package change summary
ansible.builtin.debug:
msg: '{{ _aim_patch_report }}'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Preserve native operation failure
ansible.builtin.fail:
msg: >-
The native RedHat patch operation failed. Available observed package changes and reboot state
are in the structured result. If a reboot is reported as required, reboot before retrying.
when: _aim_patch_action_failed | bool
+33
View File
@@ -0,0 +1,33 @@
---
- name: Patching | Supported platform
ansible.builtin.assert:
that:
- ansible_facts.os_family in ['Windows', 'Debian', 'RedHat']
fail_msg: 'Supported patching families: Windows, Debian, RedHat. No legacy Python bootstrap is performed.'
quiet: true
- name: Patching | Validate options
ansible.builtin.assert:
that:
- (os_patching_reboot) is boolean or (os_patching_reboot | string | lower) in ['true', 'false']
- (os_patching_rescan_after_reboot) is boolean or (os_patching_rescan_after_reboot | string | lower) in ['true', 'false']
- os_patching_reboot_timeout | int > 0
- os_patching_reboot_delay_minutes | int >= 0
- os_patching_reboot_delay_minutes | int <= 1440
- os_patching_reboot_message is string
- os_patching_reboot_message | length > 0
- os_patching_reboot_message | length <= 512
- os_patching_windows_categories is sequence
- os_patching_windows_categories is not string
- os_patching_windows_categories | length > 0
fail_msg: Invalid patching settings. Reboot/rescan flags must be boolean, reboot delay must be 0-1440 minutes and the reboot message must be 1-512 characters.
quiet: true
- name: Patching | Windows
ansible.builtin.include_tasks: windows.yml
when: ansible_facts.os_family == 'Windows'
- name: Patching | Debian
ansible.builtin.include_tasks: linux_debian.yml
when: ansible_facts.os_family == 'Debian'
- name: Patching | RedHat
ansible.builtin.include_tasks: linux_redhat.yml
when: ansible_facts.os_family == 'RedHat'
@@ -0,0 +1,162 @@
---
- name: Patching | Initialize Windows report state
ansible.builtin.set_fact:
_aim_patch_action_failed: false
_aim_patch_pre_reboot_performed: false
_aim_patch_any_reboot_performed: false
_aim_patch_preexisting_reboot_required: false
_aim_patch_preexisting_reboot_reasons: []
_aim_patch_reboot_deferred: false
_aim_patch_reboot_required_after: false
_aim_patch_blocked_reason: null
_aim_patch_continuation_required: false
_aim_patch_remaining_updates_known: false
_aim_patch_done: false
_aim_patch_cycles: 0
_aim_windows_update_runs: []
_aim_windows_searches: []
- name: Patching | Detect pending Windows reboot before patching
ansible.windows.win_reboot_info:
register: _aim_patch_pre_reboot_probe
- name: Patching | Record pre-existing Windows reboot state
ansible.builtin.set_fact:
_aim_patch_preexisting_reboot_required: '{{ _aim_patch_pre_reboot_probe.reboot_required | default(false) | bool }}'
_aim_patch_preexisting_reboot_reasons: '{{ _aim_patch_pre_reboot_probe.reboot_required_reasons | default([]) }}'
- name: Patching | Publish blocked Windows result when reboot is deferred
when:
- _aim_patch_preexisting_reboot_required | bool
- not (os_patching_reboot | bool)
block:
- name: Patching | Build blocked Windows patch report
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ 'windows' | aim_report_patch_blocked(ansible_check_mode,
os_patching_reboot_delay_minutes | int,
os_patching_rescan_after_reboot | bool,
_aim_patch_preexisting_reboot_reasons) }}
- name: AIM | Publish blocked operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Require reboot before continuing Windows patching
ansible.builtin.fail:
msg: >-
A reboot is already pending from a previous update or installation. Reboot the host first,
or rerun with "Reboot when required" enabled. No new Windows updates were started by this run.
- name: Patching | Clear pre-existing Windows reboot before patching
ansible.windows.win_reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ [2, (os_patching_reboot_delay_minutes | int) * 60] | max }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_pre_reboot
when:
- _aim_patch_preexisting_reboot_required | bool
- os_patching_reboot | bool
- not ansible_check_mode
- name: Patching | Record pre-patch Windows reboot
ansible.builtin.set_fact:
_aim_patch_pre_reboot_performed: '{{ _aim_patch_pre_reboot.rebooted | default(false) | bool }}'
_aim_patch_any_reboot_performed: '{{ _aim_patch_pre_reboot.rebooted | default(false) | bool }}'
_aim_patch_done: >-
{{ (_aim_patch_pre_reboot.rebooted | default(false) | bool) and
not (os_patching_rescan_after_reboot | bool) }}
_aim_patch_continuation_required: >-
{{ (_aim_patch_pre_reboot.rebooted | default(false) | bool) and
not (os_patching_rescan_after_reboot | bool) }}
_aim_patch_remaining_updates_known: false
- name: Patching | Search Windows updates in check mode
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: searched
reboot: false
register: _aim_windows_check_search
when:
- ansible_check_mode
- not (_aim_patch_done | bool)
- name: Patching | Record Windows check-mode search
ansible.builtin.set_fact:
_aim_windows_searches: '{{ [_aim_windows_check_search] }}'
_aim_patch_remaining_updates_known: true
_aim_patch_continuation_required: '{{ (_aim_windows_check_search.found_update_count | default(0) | int) > 0 }}'
_aim_patch_done: true
when:
- ansible_check_mode
- _aim_windows_check_search is defined
- not (_aim_windows_check_search.skipped | default(false) | bool)
- name: Patching | Process Windows patch waves
ansible.builtin.include_tasks: windows_wave.yml
loop: >-
{{ (range(1, 13) | list) if (os_patching_rescan_after_reboot | bool) else [1] }}
loop_control:
loop_var: _aim_patch_wave_number
label: 'Windows patch wave {{ _aim_patch_wave_number }}'
when:
- not ansible_check_mode
- not (_aim_patch_done | bool)
- name: Patching | Guard automatic continuation wave limit
ansible.builtin.set_fact:
_aim_patch_action_failed: true
_aim_patch_blocked_reason: cycle_limit_reached
_aim_patch_continuation_required: true
when:
- not ansible_check_mode
- os_patching_rescan_after_reboot | bool
- not (_aim_patch_done | bool)
- name: Patching | Normalize Windows update results
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ _aim_windows_update_runs |
aim_report_patch_windows_runs(
_aim_windows_searches,
ansible_check_mode,
_aim_patch_preexisting_reboot_required | bool,
_aim_patch_any_reboot_performed | bool,
os_patching_reboot | bool,
os_patching_reboot_delay_minutes | int,
os_patching_rescan_after_reboot | bool,
_aim_patch_cycles | int,
_aim_patch_continuation_required | bool,
_aim_patch_remaining_updates_known | bool,
_aim_patch_reboot_deferred | bool,
_aim_patch_reboot_required_after,
_aim_patch_blocked_reason,
not (_aim_patch_action_failed | bool),
_aim_patch_preexisting_reboot_reasons
) }}
- name: Patching | Update summary
ansible.builtin.debug:
msg: '{{ _aim_patch_report }}'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Preserve Windows update failure
ansible.builtin.fail:
msg: >-
Windows patching stopped before the approved patch wave completed. The structured result contains
successfully installed updates, bounded failed-update reasons when available, and whether another
operator-approved run is required. AIM did not replay the patch job automatically.
when: _aim_patch_action_failed | bool
@@ -0,0 +1,114 @@
---
- name: Patching | Start Windows patch cycle
ansible.builtin.set_fact:
_aim_patch_cycles: '{{ _aim_patch_cycle_number | int }}'
_aim_patch_cycle_stop: false
_aim_patch_cycle_reboot_performed: false
- name: Patching | Search available Windows updates for this wave
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: searched
reboot: false
register: _aim_windows_cycle_search
- name: Patching | Record Windows update discovery
ansible.builtin.set_fact:
_aim_windows_searches: '{{ _aim_windows_searches + [_aim_windows_cycle_search] }}'
_aim_windows_update_queue: '{{ _aim_windows_cycle_search | aim_windows_update_queue }}'
- name: Patching | Reboot when discovery itself reports a required reboot
ansible.windows.win_reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ [2, (os_patching_reboot_delay_minutes | int) * 60] | max }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_windows_search_reboot
when:
- _aim_windows_cycle_search.reboot_required | default(false) | bool
- os_patching_reboot | bool
- name: Patching | Record discovery-time reboot boundary
ansible.builtin.set_fact:
_aim_patch_cycle_stop: true
_aim_patch_cycle_reboot_performed: '{{ _aim_windows_search_reboot.rebooted | default(false) | bool }}'
_aim_patch_any_reboot_performed: >-
{{ (_aim_patch_any_reboot_performed | bool) or
(_aim_windows_search_reboot.rebooted | default(false) | bool) }}
_aim_patch_reboot_required_after: >-
{{ false if (_aim_windows_search_reboot.rebooted | default(false) | bool) else true }}
when:
- _aim_windows_search_reboot is defined
- not (_aim_windows_search_reboot.skipped | default(false) | bool)
- name: Patching | Defer discovery-time required reboot
ansible.builtin.set_fact:
_aim_patch_cycle_stop: true
_aim_patch_done: true
_aim_patch_reboot_deferred: true
_aim_patch_reboot_required_after: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: true
when:
- _aim_windows_cycle_search.reboot_required | default(false) | bool
- not (os_patching_reboot | bool)
- name: Patching | Finish when no updates are available
ansible.builtin.set_fact:
_aim_patch_done: true
_aim_patch_remaining_updates_known: true
_aim_patch_continuation_required: '{{ _aim_windows_cycle_search.reboot_required | default(false) | bool }}'
_aim_patch_reboot_required_after: '{{ _aim_windows_cycle_search.reboot_required | default(false) | bool }}'
when:
- (_aim_windows_update_queue | length) == 0
- not (_aim_patch_cycle_stop | bool)
- name: Patching | Install discovered Windows updates sequentially
ansible.builtin.include_tasks: windows_update_one.yml
loop: '{{ _aim_windows_update_queue }}'
loop_control:
loop_var: _aim_windows_update
label: '{{ _aim_windows_update.title }}'
when:
- not (_aim_patch_done | bool)
- not (_aim_patch_cycle_stop | bool)
- name: Patching | Final read-only discovery after completed non-reboot wave
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: searched
reboot: false
register: _aim_windows_cycle_final_search
when:
- not (_aim_patch_done | bool)
- not (_aim_patch_cycle_stop | bool)
- not (_aim_patch_action_failed | bool)
- name: Patching | Record final non-reboot wave state
ansible.builtin.set_fact:
_aim_windows_searches: '{{ _aim_windows_searches + [_aim_windows_cycle_final_search] }}'
_aim_patch_remaining_updates_known: true
_aim_patch_continuation_required: '{{ (_aim_windows_cycle_final_search.found_update_count | default(0) | int) > 0 }}'
_aim_patch_reboot_required_after: '{{ _aim_windows_cycle_final_search.reboot_required | default(false) | bool }}'
_aim_patch_done: true
when:
- _aim_windows_cycle_final_search is defined
- not (_aim_windows_cycle_final_search.skipped | default(false) | bool)
- name: Patching | Stop after operator-approved reboot boundary by default
ansible.builtin.set_fact:
_aim_patch_done: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
when:
- _aim_patch_cycle_reboot_performed | bool
- not (os_patching_rescan_after_reboot | bool)
- name: Patching | Continue only when post-reboot rescan was explicitly enabled
ansible.builtin.debug:
msg: >-
AIM completed a reboot boundary and will start another Windows patch cycle because
os_patching_rescan_after_reboot is explicitly enabled.
when:
- _aim_patch_cycle_reboot_performed | bool
- os_patching_rescan_after_reboot | bool
- not (_aim_patch_action_failed | bool)
@@ -0,0 +1,87 @@
---
- name: Patching | Initialize single Windows update result
ansible.builtin.set_fact:
_aim_windows_single_result: {}
_aim_windows_single_task_failed: false
- name: Patching | Install one Windows update
block:
- name: 'Patching | Install {{ _aim_windows_update.title }}'
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: installed
reboot: false
accept_list:
- '{{ _aim_windows_update.selector }}'
register: _aim_windows_single_result
rescue:
- name: Patching | Retain failed single-update result
ansible.builtin.set_fact:
_aim_windows_single_result: '{{ ansible_failed_result | default({}) }}'
_aim_windows_single_task_failed: true
- name: Patching | Append single-update evidence
ansible.builtin.set_fact:
_aim_windows_update_runs: >-
{{ _aim_windows_update_runs + [
{
'requested': _aim_windows_update,
'result': _aim_windows_single_result,
'task_failed': _aim_windows_single_task_failed | bool
}
] }}
- name: Patching | Classify single-update execution state
ansible.builtin.set_fact:
_aim_windows_single_failed: >-
{{ (_aim_windows_single_task_failed | bool) or
(_aim_windows_single_result | aim_windows_update_result_failed) }}
_aim_patch_reboot_required_after: '{{ _aim_windows_single_result.reboot_required | default(false) | bool }}'
- name: Patching | Stop this patch wave after an update failure
ansible.builtin.set_fact:
_aim_patch_action_failed: true
_aim_patch_cycle_stop: true
_aim_patch_done: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
_aim_patch_blocked_reason: '{{ _aim_windows_single_result | aim_windows_update_block_reason }}'
when: _aim_windows_single_failed | bool
- name: Patching | Reboot Windows at a sequential update boundary
ansible.windows.win_reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ [2, (os_patching_reboot_delay_minutes | int) * 60] | max }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_windows_single_reboot
when:
- not (_aim_windows_single_failed | bool)
- _aim_windows_single_result.reboot_required | default(false) | bool
- os_patching_reboot | bool
- name: Patching | Record completed sequential reboot boundary
ansible.builtin.set_fact:
_aim_patch_cycle_stop: true
_aim_patch_cycle_reboot_performed: '{{ _aim_windows_single_reboot.rebooted | default(false) | bool }}'
_aim_patch_any_reboot_performed: >-
{{ (_aim_patch_any_reboot_performed | bool) or
(_aim_windows_single_reboot.rebooted | default(false) | bool) }}
_aim_patch_reboot_required_after: >-
{{ false if (_aim_windows_single_reboot.rebooted | default(false) | bool)
else (_aim_windows_single_result.reboot_required | default(false) | bool) }}
when:
- _aim_windows_single_reboot is defined
- not (_aim_windows_single_reboot.skipped | default(false) | bool)
- name: Patching | Defer required reboot and stop the current patch wave
ansible.builtin.set_fact:
_aim_patch_cycle_stop: true
_aim_patch_done: true
_aim_patch_reboot_deferred: true
_aim_patch_reboot_required_after: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
when:
- not (_aim_windows_single_failed | bool)
- _aim_windows_single_result.reboot_required | default(false) | bool
- not (os_patching_reboot | bool)
@@ -0,0 +1,124 @@
---
- name: Patching | Start Windows patch wave
ansible.builtin.set_fact:
_aim_patch_cycles: '{{ _aim_patch_wave_number | int }}'
_aim_patch_wave_task_failed: false
_aim_patch_wave_result: {}
_aim_patch_wave_failed: false
_aim_patch_wave_reboot_performed: false
- name: Patching | Install current Windows update wave
block:
- name: Patching | Install all currently selected Windows updates
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: installed
reboot: false
register: _aim_patch_wave_result
rescue:
- name: Patching | Retain failed Windows update wave result
ansible.builtin.set_fact:
_aim_patch_wave_result: '{{ ansible_failed_result | default({}) }}'
_aim_patch_wave_task_failed: true
- name: Patching | Append Windows update wave evidence
ansible.builtin.set_fact:
_aim_windows_update_runs: >-
{{ _aim_windows_update_runs + [
{
'result': _aim_patch_wave_result,
'task_failed': _aim_patch_wave_task_failed | bool,
'wave': _aim_patch_wave_number | int
}
] }}
- name: Patching | Classify Windows update wave
ansible.builtin.set_fact:
_aim_patch_wave_failed: >-
{{ (_aim_patch_wave_task_failed | bool) or
(_aim_patch_wave_result | aim_windows_update_result_failed) }}
_aim_patch_reboot_required_after: '{{ _aim_patch_wave_result.reboot_required | default(false) | bool }}'
- name: Patching | Record Windows update wave failure
ansible.builtin.set_fact:
_aim_patch_action_failed: true
_aim_patch_done: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
_aim_patch_blocked_reason: '{{ _aim_patch_wave_result | aim_windows_update_block_reason }}'
when: _aim_patch_wave_failed | bool
- name: Patching | Reboot after the completed Windows update wave
ansible.windows.win_reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ [2, (os_patching_reboot_delay_minutes | int) * 60] | max }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_wave_reboot
when:
- _aim_patch_wave_result.reboot_required | default(false) | bool
- os_patching_reboot | bool
- name: Patching | Record completed Windows wave reboot boundary
ansible.builtin.set_fact:
_aim_patch_wave_reboot_performed: '{{ _aim_patch_wave_reboot.rebooted | default(false) | bool }}'
_aim_patch_any_reboot_performed: >-
{{ (_aim_patch_any_reboot_performed | bool) or
(_aim_patch_wave_reboot.rebooted | default(false) | bool) }}
_aim_patch_reboot_required_after: >-
{{ false if (_aim_patch_wave_reboot.rebooted | default(false) | bool)
else (_aim_patch_wave_result.reboot_required | default(false) | bool) }}
when:
- _aim_patch_wave_reboot is defined
- not (_aim_patch_wave_reboot.skipped | default(false) | bool)
- name: Patching | Defer required reboot after Windows update wave
ansible.builtin.set_fact:
_aim_patch_done: true
_aim_patch_reboot_deferred: true
_aim_patch_reboot_required_after: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
when:
- not (_aim_patch_wave_failed | bool)
- _aim_patch_wave_result.reboot_required | default(false) | bool
- not (os_patching_reboot | bool)
- name: Patching | Stop after approved Windows reboot boundary by default
ansible.builtin.set_fact:
_aim_patch_done: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
when:
- _aim_patch_wave_reboot_performed | bool
- not (os_patching_rescan_after_reboot | bool)
- name: Patching | Stop automatic continuation after a failed Windows wave
ansible.builtin.set_fact:
_aim_patch_done: true
_aim_patch_continuation_required: true
_aim_patch_remaining_updates_known: false
when:
- _aim_patch_wave_failed | bool
- name: Patching | Final read-only discovery after completed non-reboot Windows wave
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: searched
reboot: false
register: _aim_windows_wave_final_search
when:
- not (_aim_patch_done | bool)
- not (_aim_patch_wave_reboot_performed | bool)
- not (_aim_patch_wave_result.reboot_required | default(false) | bool)
- not (_aim_patch_wave_failed | bool)
- name: Patching | Record completed non-reboot Windows wave state
ansible.builtin.set_fact:
_aim_windows_searches: '{{ _aim_windows_searches + [_aim_windows_wave_final_search] }}'
_aim_patch_remaining_updates_known: true
_aim_patch_continuation_required: '{{ (_aim_windows_wave_final_search.found_update_count | default(0) | int) > 0 }}'
_aim_patch_reboot_required_after: '{{ _aim_windows_wave_final_search.reboot_required | default(false) | bool }}'
_aim_patch_done: true
when:
- _aim_windows_wave_final_search is defined
- not (_aim_windows_wave_final_search.skipped | default(false) | bool)
+12
View File
@@ -0,0 +1,12 @@
# maintenance_reboot_hosts
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
maintenance_reboot_timeout: 1800
maintenance_reboot_message: Reboot initiated by debsansible01.bfmiglabor.lan (Ansible)
maintenance_reboot_pre_delay: 0
maintenance_reboot_post_delay: 15
```
@@ -0,0 +1,6 @@
---
maintenance_reboot_timeout: 1800
maintenance_reboot_message: Reboot initiated by debsansible01.bfmiglabor.lan (Ansible)
maintenance_reboot_pre_delay: 0
maintenance_reboot_post_delay: 15
@@ -0,0 +1,26 @@
---
- name: Reboot | Validate timing
ansible.builtin.assert:
that:
- maintenance_reboot_timeout | int > 0
- maintenance_reboot_pre_delay | int >= 0
- maintenance_reboot_post_delay | int >= 0
fail_msg: Reboot timeout must be positive; delays must be non-negative.
quiet: true
- name: Reboot | linux
ansible.builtin.reboot:
msg: '{{ maintenance_reboot_message }}'
reboot_timeout: '{{ maintenance_reboot_timeout | int }}'
pre_reboot_delay: '{{ maintenance_reboot_pre_delay | int }}'
post_reboot_delay: '{{ maintenance_reboot_post_delay | int }}'
test_command: whoami
when: '''linux'' in group_names'
- name: Reboot | windows
ansible.windows.win_reboot:
msg: '{{ maintenance_reboot_message }}'
reboot_timeout: '{{ maintenance_reboot_timeout | int }}'
pre_reboot_delay: '{{ [maintenance_reboot_pre_delay | int, 2] | max }}'
post_reboot_delay: '{{ maintenance_reboot_post_delay | int }}'
connect_timeout: 30
when: '''windows'' in group_names'
@@ -0,0 +1,19 @@
# maintenance_start_stopped_services
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
maintenance_service_include: []
maintenance_service_exclude: []
maintenance_service_fail_on_error: true
```
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -0,0 +1,5 @@
---
maintenance_service_include: []
maintenance_service_exclude: []
maintenance_service_fail_on_error: true
@@ -0,0 +1,55 @@
- name: Services | Validate selections
ansible.builtin.assert:
that:
- maintenance_service_include is sequence
- maintenance_service_include is not string
- maintenance_service_exclude is sequence
- maintenance_service_exclude is not string
- (maintenance_service_fail_on_error) is boolean or (maintenance_service_fail_on_error | string |
lower) in ['true', 'false']
fail_msg: Service selections must be lists of internal names; failure policy must be boolean.
quiet: true
- name: Services | Read current state
ansible.windows.win_service_info: {}
register: _aim_services
- name: Services | Start eligible stopped services
ansible.windows.win_service:
name: '{{ item.name }}'
state: started
loop: '{{ _aim_services.services }}'
loop_control:
label: '{{ item.name }}'
when:
- item.state == 'stopped'
- item.start_mode in ['auto', 'delayed']
- maintenance_service_include | length == 0 or item.name in maintenance_service_include
- item.name not in maintenance_service_exclude
register: _aim_service_starts
ignore_errors: true
- name: Services | Observe states after start attempts
ansible.windows.win_service_info: {}
register: _aim_services_after
- name: Services | Build before and after report
ansible.builtin.set_fact:
_aim_service_report: '{{ _aim_services.services | aim_report_services(_aim_service_starts.results | default([]),
_aim_services_after.services, maintenance_service_include, maintenance_service_exclude, ansible_check_mode)
}}'
- name: Services | Summary
ansible.builtin.debug:
msg: '{{ _aim_service_report }}'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: service_start_summary_v1
data: '{{ _aim_service_report }}'
- name: Services | Report partial failure
ansible.builtin.fail:
msg: One or more attempted services are not running. See failed_to_start in the structured report.
when:
- maintenance_service_fail_on_error | bool
- _aim_service_report.failed_count | int > 0
- not ansible_check_mode
+3
View File
@@ -0,0 +1,3 @@
# pfsense_apply_baseline
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
+153
View File
@@ -0,0 +1,153 @@
---
# Policy-preserving extraction from configure_pfsense_initial.yml. Do not change rule values without separate approval.
- name: Check current bell state
ansible.builtin.raw: sysctl -n hw.syscons.bell
register: bell_state
changed_when: false
- name: Disable startup/shutdown beep
ansible.builtin.raw: sysctl hw.syscons.bell=0
when: bell_state.stdout.strip() == "1"
changed_when: true
- name: Create alias bf_wan_extern
pfsensible.core.pfsense_alias:
name: bf_wan_extern
descr: bitformer WAN IP Adressen
address: 217.13.70.132 87.138.207.238 80.152.155.27 217.13.174.202
type: host
state: present
- name: Create alias bf_wartung
pfsensible.core.pfsense_alias:
name: bf_wartung
descr: bitformer Wartungs-IP
address: 10.240.0.1
type: host
state: present
- name: Create alias rfc_1918_5735
pfsensible.core.pfsense_alias:
name: rfc_1918_5735
descr: RFC1918, RFC5735 (private IPs)
address: 10.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16
type: network
state: present
- name: 'Add NAT outbound traffic rule (Port: 500)'
pfsensible.core.pfsense_nat_outbound:
descr: 'Outbound NAT for private IP space (Port: 500)'
interface: wan
address: null
source: rfc_1918_5735
destination: any:500
staticnatport: true
state: present
- name: Add NAT outbound traffic rule
pfsensible.core.pfsense_nat_outbound:
descr: Outbound NAT for private IP space
interface: wan
address: null
source: rfc_1918_5735
destination: any
state: present
- name: 'Add firewall rule: Allow Ping'
pfsensible.core.pfsense_rule:
name: Allow Ping
action: pass
interface: wan
ipprotocol: inet
protocol: icmp
icmptype: echoreq
source: any
destination: IP:wan
log: true
state: present
- name: 'Add firewall rule: Allow Webinterface access'
pfsensible.core.pfsense_rule:
name: bitformer Webinterface access rule
action: pass
interface: wan
ipprotocol: inet
protocol: tcp
destination_port: 443
source: bf_wan_extern
destination: IP:wan
log: true
state: present
- name: Create Anti-Lockout ports alias
pfsensible.core.pfsense_alias:
name: anti_lockout_ports
type: port
address: 22 80 443
descr: Ports for Anti-Lockout access
- name: Add custom Anti-Lockout Rule
pfsensible.core.pfsense_rule:
name: Custom Anti-Lockout Rule
action: pass
interface: wan
ipprotocol: inet
protocol: tcp
destination_port: anti_lockout_ports
source: any
destination: IP:wan
log: true
state: present
- name: Add bitconnect VPN CA 2021
pfsensible.core.pfsense_ca:
name: bitconnect VPN CA 2021
certificate: |
-----BEGIN CERTIFICATE-----
MIIFbDCCA1SgAwIBAgIUWV573JfAztSareWb4jnkNIdlEt8wDQYJKoZIhvcNAQEL
BQAwITEfMB0GA1UEAwwWYml0Y29ubmVjdCBWUE4gQ0EgMjAyMTAeFw0yMTEwMDgx
NjA1MzNaFw0zMTEwMDYxNjA1MzNaMCExHzAdBgNVBAMMFmJpdGNvbm5lY3QgVlBO
IENBIDIwMjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDjjoWk81zG
vmdKCICW27cnQV6kmDwwXezC7cdmk8nVKnlcJAnVPExYV1M1wa9OYDgjb+Jc7vEV
UKKc7h/JtWt5OSg7aLq5eh6ZZminYG+lrKC7CFhyPnKuLPW4D6ye6iTVpwlhMMbv
fCiinuA2shniQtX21QYc8jxKdJnmfgv7/JJ0BxnWCyE8yn1xy6DyjPH9ystzKFGO
C3HH2wH2+sgKuiyk+8yxEF3hktMIDZ/D1gTyw8wsL4PgOs78EBSf0UKjAaBBjem8
rICxBo4yh7YvVJ+MMLc+2IMcyM3wpYPbMpA/0hXoWsAeYEOvrZR+MYQ08cQw8QEk
MHetIjbksd9D1OSdMfghr+A+dxVpQWTOnUnG48L84E/6RD0STyz/uJjNDJ5Qn4uV
8e6ELHbbPiWVQWw+kg8tVetH6+WELXf/7pUnV9uYr7DvijEROP6l1IX/r92qC270
/QFiadYX0lroqaWdwk5z7DFnVVcCHqchygS97exzDg68LkSJ5pOZ6spIr9WfaGxD
3dva4ekC/HEZUdau+NnBPnOCLD6EqOnh3RAJosgX6/eb5LHhk5agruM+1PZcWPiL
5D0HvNjKOCGXW2yVd1fAdOy0onP4OQHK3gJPNFJ9m/LXnn5+CHvYct+3qDlxZcCR
qH9QBE7kC/8pRmHZqC1g0rn8yiQ012eCpwIDAQABo4GbMIGYMB0GA1UdDgQWBBQ4
pYw9Df2Ln2pUE/xRDjhebugWpTBcBgNVHSMEVTBTgBQ4pYw9Df2Ln2pUE/xRDjhe
bugWpaElpCMwITEfMB0GA1UEAwwWYml0Y29ubmVjdCBWUE4gQ0EgMjAyMYIUWV57
3JfAztSareWb4jnkNIdlEt8wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJ
KoZIhvcNAQELBQADggIBAN1OOdv5rDgtBhYnmnId4iifvjzKQEQF5go4cJDueUo4
86u6xJrv83sC53FKxaAcNZUxJEcFFBHKlCUTNADsKDdQxIPA2Ow6goIx914VbFO/
OmkFWS+53o4V8zRrwTxJi3Ps0R3sgp3pok5fQNL30tMZIf1Ug05jOqSCT8GBzIS8
wwSw6aNi/Zcs9sBuaEEap47faTowk53EJykUd8htzH/3E5ioi3hE8TsZYPKb4Frk
mMqRbX6N78fZ0xOIewh58S4eeGlRCGlRs45ciVxuryTaloFfDDBFFBR3V4q4Y/y9
dvjiRmDs4fod1ZGEFUfVyDPXjzWCUUQiMHxUoh9s06i5zO3YCB/mkh+11ohyE109
ciN495vhpTONQ8GzXLc87GjVUow7btn3lfaMf1sTfLhAueHNNbDHTnhRFkUtrdCx
73+MYpiSlLpBxnyLkTM4umYXeYNN5Od0UjYZZqlLK9MNZrM5CwVxjRxJjgV6Nbap
4Apnfqi+d3Ulnc6Zk8w0tiVcRfrLR6EVA3JEHqFQLuXbU1+K8C0N9YNFHy2iGAxF
Ysx7aJVvmzyoiB06/qQrHcjeizVJaqR7w6+1cuTKo+fdvp2KtyK8+pFtQt4n+unw
3eLC1NdcEyWBtlKqG6sjSXCBCgc1z2wAOfR+sQsH64uVHqxND4rPo8X4uo28Jgv9
-----END CERTIFICATE-----
state: present
- name: Add bitconnect VPN-Client
pfsensible.core.pfsense_openvpn_client:
name: bitformer Wartungs-VPN
ca: bitconnect VPN CA 2021
cert: bf-customers-vpn01
create_gw: both
data_ciphers:
- AES-256-GCM
- AES-256-CBC
- AES-128-GCM
- CHACHA20-POLY1305
data_ciphers_fallback: AES-256-CBC
dev_mode: tun
digest: SHA384
interface: any
mode: p2p_tls
protocol: UDP4
server_addr: vpngw01.bitformer.net
server_port: 42030
state: present
- name: Print left over manual settings to configure
ansible.builtin.debug:
msg:
- 'Manuelle Einstellungen müssen vorgenommen werden:'
- 'Firewall Max Table Entries: 500000'
- Disable startup/shutdown beep
- Password protect the console
@@ -0,0 +1,3 @@
# pfsense_install_prerequisites
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
@@ -0,0 +1,7 @@
---
# Policy-preserving extraction from configure_pfsense_initial.yml. Do not change rule values without separate approval.
- name: Install package
ansible.builtin.package:
name:
- pfSense-pkg-sudo
state: present
@@ -1,12 +0,0 @@
---
ad_ds_feature_name: "AD-Domain-Services"
dhcp_windows_service_name: "DHCPServer"
veeam_services:
vbr: "VeeamBackupSvc"
vbo: "Veeam.Archiver.Service"
em: "VeeamEnterpriseManagerSvc"
unifi_linux_services:
- unifi
- unifi.service
unifi_linux_packages:
- unifi
@@ -1,6 +0,0 @@
---
galaxy_info:
role_name: server_role_selection
description: Detect server roles used for Checkmk deployment decisions
min_ansible_version: "2.18"
dependencies: []
-111
View File
@@ -1,111 +0,0 @@
---
# ==========================
# WINDOWS DETECTION
# ==========================
- name: "Windows | Detect AD DS feature (DC)"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_feature_info:
name: "{{ ad_ds_feature_name }}"
register: _win_dc_feature
failed_when: false
- name: "Windows | Fallback: check NTDS service (DC)"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: "NTDS"
register: _win_ntds_svc
failed_when: false
- name: "Windows | Check DHCP service"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: "{{ dhcp_windows_service_name }}"
register: _win_dhcp_svc
failed_when: false
- name: "Windows | Check Veeam VBR service"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: "{{ veeam_services.vbr }}"
register: _veeam_vbr
failed_when: false
- name: "Windows | Check Veeam VBO service"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: "{{ veeam_services.vbo }}"
register: _veeam_vbo
failed_when: false
- name: "Windows | Check Veeam Enterprise Manager service"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: "{{ veeam_services.em }}"
register: _veeam_em
failed_when: false
- name: "Windows | Check Hyper-V service"
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: "vmms"
register: _win_hyperv_svc
failed_when: false
- name: "Windows | Set detection booleans"
when: ansible_facts['os_family'] == "Windows"
ansible.builtin.set_fact:
is_dc: >-
{{
(((_win_dc_feature.features | default([])) | selectattr('installed') | list | length) > 0)
or (_win_ntds_svc.exists | default(false))
}}
is_dhcp_server: "{{ _win_dhcp_svc.exists | default(false) }}"
has_veeam_vbr: "{{ _veeam_vbr.exists | default(false) }}"
has_veeam_vbo: "{{ _veeam_vbo.exists | default(false) }}"
has_veeam_em: "{{ _veeam_em.exists | default(false) }}"
is_hyperv_host: "{{ _win_hyperv_svc.exists | default(false) }}"
- name: "Windows | Debug summary"
when: ansible_facts['os_family'] == "Windows"
ansible.builtin.debug:
msg:
is_dc: "{{ is_dc }}"
is_dhcp_server: "{{ is_dhcp_server }}"
has_veeam_vbr: "{{ has_veeam_vbr }}"
has_veeam_vbo: "{{ has_veeam_vbo }}"
has_veeam_em: "{{ has_veeam_em }}"
is_hyperv_host: "{{ is_hyperv_host }}"
# ==========================
# LINUX DETECTION
# ==========================
- name: "Linux | Collect service facts"
when: ansible_facts['os_family'] != "Windows"
ansible.builtin.service_facts:
- name: "Linux | Collect package facts"
when: ansible_facts['os_family'] != "Windows"
ansible.builtin.package_facts:
manager: auto
- name: "Linux | Set UniFi flag"
when: ansible_facts['os_family'] != "Windows"
vars:
svcs: "{{ ansible_facts.services | default({}) }}"
pkgs: "{{ ansible_facts.packages | default({}) | list }}"
ansible.builtin.set_fact:
is_unifi_controller: >-
{{
(unifi_linux_services | select('in', svcs.keys()) | list | length > 0)
or (pkgs | intersect(unifi_linux_packages) | length > 0)
}}
- name: "Normalize detection booleans"
ansible.builtin.set_fact:
is_dc: "{{ is_dc | default(false) }}"
is_dhcp_server: "{{ is_dhcp_server | default(false) }}"
has_veeam_vbr: "{{ has_veeam_vbr | default(false) }}"
has_veeam_vbo: "{{ has_veeam_vbo | default(false) }}"
has_veeam_em: "{{ has_veeam_em | default(false) }}"
is_hyperv_host: "{{ is_hyperv_host | default(false) }}"
is_unifi_controller: "{{ is_unifi_controller | default(false) }}"
+3
View File
@@ -0,0 +1,3 @@
# sophos_apply_baseline
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
+500
View File
@@ -0,0 +1,500 @@
---
# Policy-preserving extraction from configure_sophos_initial_bitformer_config.yml. Do not change rule values without separate approval.
- name: Erstelle 'bf_wan' IP Liste
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: IPHost
data: |
<IPHost>
<Name>bf_wan</Name>
<Description>WAN-IPs von bitformer</Description>
<HostType>IPList</HostType>
<ListOfIPAddresses>217.13.70.132,87.138.207.238,80.152.155.27,217.13.174.202</ListOfIPAddresses>
</IPHost>
state: present
- name: Erstelle 'bf_wartung' IP-Host
sophos.sophos_firewall.sfos_ip_host:
name: bf_wartung
ip_address: 10.240.0.1
state: present
- name: Netzwerke als IP-Hosts in der Firewall anlegen
sophos.sophos_firewall.sfos_ip_host:
name: '{{ item.name }}'
network: '{{ item.network }}'
mask: '{{ item.subnetmask }}'
host_type: network
state: present
loop: '{{ network_hosts }}'
- name: Erstelle 'rfc_1918_5735' Gruppe
sophos.sophos_firewall.sfos_ip_hostgroup:
name: rfc_1918_5735
description: rfc_1918_5735
host_list:
- rfc_1918_a
- rfc_1918_b
- rfc_1918_c
- rfc_5735
state: present
- name: Erstelle 'OpenVPN' Service
sophos.sophos_firewall.sfos_service:
name: OpenVPN
type: tcporudp
service_list:
- protocol: udp
src_port: 1:65535
dst_port: 1194
state: present
- name: Erstelle 'dgrp_wan_access_guests' Service Group
sophos.sophos_firewall.sfos_servicegroup:
name: dgrp_wan_access_guests
description: WAN Access Guests
service_list:
- PING
- HTTP
- HTTPS
- SMTPS_465
- SMTPS
- IMAP
- IMAPS
- POP3S
- IKE
- OpenVPN
state: present
- name: Erstelle 'dgrp_wan_access_office' Service Group
sophos.sophos_firewall.sfos_servicegroup:
name: dgrp_wan_access_office
description: WAN Access Office
service_list:
- PING
- SSH
- HTTP
- HTTPS
state: present
- name: Erstelle bitformer Management Access ACL Ausnahmeregel
sophos.sophos_firewall.sfos_service_acl_exception:
name: bitformer Management Access
description: Allow Management-Access to Webinterface, PING and SSH
position: bottom
source_zone: WAN
source_list:
- bf_wan
service_list:
- HTTPS
- SSH
- PING
action: accept
state: present
- name: Erstelle bitformer Monitoring ACL Ausnahmeregel
sophos.sophos_firewall.sfos_service_acl_exception:
name: bitformer Monitoring
description: Allow Monitoring-Access
position: bottom
source_zone: VPN
source_list:
- bf_wartung
service_list:
- DNS
- HTTPS
- SSH
- PING
action: accept
state: present
- name: Erstelle UserPortal Country-Restricted ACL Ausnahmeregel
sophos.sophos_firewall.sfos_service_acl_exception:
name: UserPortal Country-Restricted
description: Allow UserPort from Selected Countries
position: bottom
source_zone: WAN
source_list:
- Germany
- Austria
- Switzerland
service_list:
- UserPortal
action: accept
state: present
- name: Erstelle 'bitformer' IPSec Profile
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VPNProfile
data: |
<VPNProfile>
<Name>bitformer</Name>
<Description>IPSec Policy bitformer Wartungszugang</Description>
<KeyingMethod>Automatic</KeyingMethod>
<AllowReKeying>Enable</AllowReKeying>
<KeyNegotiationTries>0</KeyNegotiationTries>
<AuthenticationMode>MainMode</AuthenticationMode>
<PassDataInCompressedFormat>Disable</PassDataInCompressedFormat>
<UseStrictProfile>Disable</UseStrictProfile>
<Phase1>
<EncryptionAlgorithm1>AES256</EncryptionAlgorithm1>
<AuthenticationAlgorithm1>SHA2_256</AuthenticationAlgorithm1>
<EncryptionAlgorithm2/>
<AuthenticationAlgorithm2/>
<EncryptionAlgorithm3/>
<AuthenticationAlgorithm3/>
<SupportedDHGroups>
<DHGroup>16(DH4096)</DHGroup>
</SupportedDHGroups>
<KeyLife>28800</KeyLife>
<ReKeyMargin>360</ReKeyMargin>
<RandomizeRe-KeyingMarginBy>50</RandomizeRe-KeyingMarginBy>
<DeadPeerDetection>Enable</DeadPeerDetection>
<CheckPeerAfterEvery>10</CheckPeerAfterEvery>
<WaitForResponseUpto>25</WaitForResponseUpto>
<ActionWhenPeerUnreachable>ReInitiate</ActionWhenPeerUnreachable>
</Phase1>
<Phase2>
<EncryptionAlgorithm1>AES256</EncryptionAlgorithm1>
<AuthenticationAlgorithm1>SHA2_256</AuthenticationAlgorithm1>
<EncryptionAlgorithm2/>
<AuthenticationAlgorithm2/>
<EncryptionAlgorithm3/>
<AuthenticationAlgorithm3/>
<PFSGroup>SameasPhase-I</PFSGroup>
<KeyLife>3600</KeyLife>
</Phase2>
<sha2_96_truncate>no</sha2_96_truncate>
<keyexchange>ikev2</keyexchange>
</VPNProfile>
state: present
- name: Erstelle 'Mitarbeiter IPSec VPN' IPSec Profile
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VPNProfile
data: |
<VPNProfile transactionid="">
<Name>Mitarbeiter IPSec VPN</Name>
<Description>IPSec VPN für Mitarbeiter</Description>
<KeyingMethod>Automatic</KeyingMethod>
<AllowReKeying>Enable</AllowReKeying>
<KeyNegotiationTries>0</KeyNegotiationTries>
<AuthenticationMode>MainMode</AuthenticationMode>
<PassDataInCompressedFormat>Disable</PassDataInCompressedFormat>
<Phase1>
<EncryptionAlgorithm1>AES256</EncryptionAlgorithm1>
<AuthenticationAlgorithm1>SHA2_256</AuthenticationAlgorithm1>
<EncryptionAlgorithm2>AES256</EncryptionAlgorithm2>
<AuthenticationAlgorithm2>SHA2_384</AuthenticationAlgorithm2>
<EncryptionAlgorithm3/>
<AuthenticationAlgorithm3/>
<SupportedDHGroups>
<DHGroup>14(DH2048)</DHGroup>
<DHGroup>16(DH4096)</DHGroup>
<DHGroup>18(DH8192)</DHGroup>
<DHGroup>19(ecp256)</DHGroup>
<DHGroup>21(ecp521)</DHGroup>
<DHGroup>31(curve25519)</DHGroup>
</SupportedDHGroups>
<KeyLife>36000</KeyLife>
<ReKeyMargin>360</ReKeyMargin>
<RandomizeRe-KeyingMarginBy>100</RandomizeRe-KeyingMarginBy>
<DeadPeerDetection>Enable</DeadPeerDetection>
<CheckPeerAfterEvery>60</CheckPeerAfterEvery>
<WaitForResponseUpto>240</WaitForResponseUpto>
<ActionWhenPeerUnreachable>Disconnect</ActionWhenPeerUnreachable>
</Phase1>
<Phase2>
<EncryptionAlgorithm1>AES256</EncryptionAlgorithm1>
<AuthenticationAlgorithm1>SHA2_256</AuthenticationAlgorithm1>
<EncryptionAlgorithm2>AES256</EncryptionAlgorithm2>
<AuthenticationAlgorithm2>SHA2_384</AuthenticationAlgorithm2>
<EncryptionAlgorithm3/>
<AuthenticationAlgorithm3/>
<PFSGroup>SameasPhase-I</PFSGroup>
<KeyLife>32400</KeyLife>
</Phase2>
<sha2_96_truncate>no</sha2_96_truncate>
<keyexchange>ikev1</keyexchange>
</VPNProfile>
state: present
- name: Update LAN Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: LAN
https: Enable
ssh: Enable
ad_sso: Enable
captive_portal: Enable
radius_sso: Disable
client_authen: Enable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Enable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Enable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update WAN Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: WAN
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Disable
ipsec: Enable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update DMZ Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: DMZ
https: Disable
ssh: Enable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Disable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update VPN Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: VPN
https: Enable
ssh: Enable
ad_sso: Disable
captive_portal: Enable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Enable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Enable
smtp_relay: Disable
snmp: Enable
state: updated
- name: Update WiFi Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: WiFi
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Disable
dns: Disable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Entferne 'Auto added firewall policy for MTA' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Auto added firewall policy for MTA
state: absent
- name: Erstelle 'LAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WAN
action: accept
description: Lan > WAN Regel
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Any
src_networks:
- Any
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN > WAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: LAN > WAN
description: Lan to WAN group
policy_list:
- LAN_to_WAN
policy_type: Any
source_zones:
- LAN
dest_zones:
- WAN
state: present
- name: Erstelle 'bitformer Wartungszugang' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: bitformer Wartungszugang
action: accept
description: bitconnect Zugriff
log: enable
status: enable
position: bottom
src_zones:
- VPN
dst_zones:
- Any
src_networks:
- bf_wartung
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'bitformer SPN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: bitformer SPN
action: accept
description: Zugriff auf bitformer SPN
log: enable
status: enable
position: bottom
src_zones:
- VPN
dst_zones:
- Any
src_networks:
- bf_spn_network
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_bitformer_SPN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_bitformer_SPN
action: accept
description: Zugriff auf bitformer SPN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- VPN
src_networks:
- Any
dst_networks:
- bf_spn_network
service_list:
- Any
state: present
- name: Erstelle 'bitformer' Firewall Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: bitformer
description: bitformer group
policy_list:
- bitformer Wartungszugang
- bitformer SPN
- LAN_to_bitformer_SPN
policy_type: Any
source_zones:
- Any
dest_zones:
- Any
state: present
- name: Erstelle 'VPN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: VPN_to_WAN
action: accept
description: Zugriff von VPN
log: enable
status: disable
position: bottom
src_zones:
- VPN
dst_zones:
- LAN
src_networks:
- Any
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'VPN' Firewall Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: VPN
description: VPN group
policy_list:
- VPN_to_WAN
policy_type: Any
source_zones:
- Any
dest_zones:
- Any
state: present
- name: Entferne [example] Firewallregeln
sophos.sophos_firewall.sfos_firewall_rule:
name: '{{ item }}'
state: absent
loop: '{{ firewall_rules_to_remove }}'
- name: Erstelle 'DROP_ALL_LOG' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: DROP_ALL_LOG
action: drop
description: Verwirft alle Pakete mit Log
log: enable
status: enable
position: bottom
src_zones:
- Any
dst_zones:
- Any
src_networks:
- Any
dst_networks:
- Any
service_list:
- Any
state: present
- name: Aktiviere 'Vordefinierten NTP-Server verwenden'
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: Time
data: |
<Time>
<TimeZone>Europe/Berlin</TimeZone>
<SetDateTime>
<Date>
<Year/>
<Month/>
<Day/>
</Date>
<Time>
<HH/>
<MM/>
<SS>0</SS>
</Time>
</SetDateTime>
<PredefinedNTPServer>Enable</PredefinedNTPServer>
</Time>
state: updated
+3
View File
@@ -0,0 +1,3 @@
# sophos_customer_bluuunit
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
@@ -0,0 +1,527 @@
---
# Customer-specific firewall policy preserved from the uploaded source.
- name: Update hostname settings
sophos.sophos_firewall.sfos_admin_settings:
hostname_settings:
hostname: '{{ hostname }}'
state: updated
- name: Netzwerke als IP-Hosts in der Firewall anlegen
sophos.sophos_firewall.sfos_ip_host:
name: '{{ item.value.name }}'
network: '{{ item.value.network }}'
mask: '{{ item.value.subnetmask }}'
host_type: network
state: present
loop: '{{ network_objects | dict2items }}'
- name: Zonen erstellen
sophos.sophos_firewall.sfos_zone:
name: '{{ item.value.zone_name }}'
description: '{{ item.value.zone_description }}'
zone_type: '{{ item.value.zone_type }}'
state: present
loop: '{{ vlan_interfaces | dict2items }}'
when: item.value.name != "LAN"
- name: Update Management Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Management
https: Enable
ssh: Enable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update Server Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Server
https: Enable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update Guest Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Guest
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update Facility Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Facility
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update VOIP Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: VOIP
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Add VLAN Interfaces
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VLAN
data: |
<VLAN>
<Name>{{ item.value.name }}</Name>
<Hardware>Port1</Hardware>
<Interface>Port1</Interface>
<Zone>{{ item.value.zone_name }}</Zone>
<VLANID>{{ item.value.vlan_id }}</VLANID>
<IPv4Configuration>Enable</IPv4Configuration>
<IPv4Assignment>Static</IPv4Assignment>
<IPAddress>{{ item.value.ip_address }}</IPAddress>
<Netmask>{{ item.value.subnetmask }}</Netmask>
</VLAN>
state: present
loop: '{{ vlan_interfaces | dict2items }}'
loop_control:
label: '{{ item.key }} -> VLAN {{ item.value.vlan_id }}'
- name: Erstelle 'LAN_to_LAN_old' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_LAN_old
action: accept
description: Erlaubt Zugriff von LAN auf Bestandsnetz
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- LAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.lan_old.name }}'
service_list:
- Any
state: present
- name: Erstelle 'INTERNAL_to_bu_RZ' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: INTERNAL_to_bu_RZ
action: accept
description: Erlaubt Zugriff von internen Netzen auf bluu unit Rechenzentrum
log: enable
status: enable
position: bottom
src_zones:
- Facility
- Guest
- LAN
- Management
- Server
- VOIP
dst_zones:
- VPN
src_networks:
- '{{ network_objects.facility.name }}'
- '{{ network_objects.guest.name }}'
- '{{ network_objects.lan_old.name }}'
- '{{ network_objects.management.name }}'
- '{{ network_objects.office.name }}'
- '{{ network_objects.server.name }}'
- '{{ network_objects.voip.name }}'
dst_networks:
- '{{ network_objects.derz_lan.name }}'
service_list:
- Any
state: present
- name: Erstelle 'SSLVPN_to_INTERNAL' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: SSLVPN_to_INTERNAL
action: accept
description: Erlaubt Zugriff von DERZ SSLVPN auf internen Netzen
log: enable
status: enable
position: bottom
src_zones:
- VPN
dst_zones:
- Facility
- LAN
- Server
- VOIP
src_networks:
- '{{ network_objects.derz_sslvpn.name }}'
dst_networks:
- '{{ network_objects.facility.name }}'
- '{{ network_objects.lan_old.name }}'
- '{{ network_objects.office.name }}'
- '{{ network_objects.server.name }}'
- '{{ network_objects.voip.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WAN
action: accept
description: Erlaubt Zugriff von LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_old_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_old_to_WAN
action: accept
description: Erlaubt Zugriff von old LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.lan_old.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Server_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Server_to_WAN
action: accept
description: Erlaubt Zugriff von Server auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Server
dst_zones:
- WAN
src_networks:
- '{{ network_objects.server.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Management_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Management_to_WAN
action: accept
description: Erlaubt Zugriff von Management auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Management
dst_zones:
- WAN
src_networks:
- '{{ network_objects.management.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Guest_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Guest_to_WAN
action: accept
description: Erlaubt Zugriff von Guest auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Guest
dst_zones:
- WAN
src_networks:
- '{{ network_objects.guest.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Facility_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Facility_to_WAN
action: accept
description: Erlaubt Zugriff von Facility auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Facility
dst_zones:
- WAN
src_networks:
- '{{ network_objects.facility.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'VOIP_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: VOIP_to_WAN
action: accept
description: Erlaubt Zugriff von VOIP auf WAN
log: enable
status: enable
position: bottom
src_zones:
- VOIP
dst_zones:
- WAN
src_networks:
- '{{ network_objects.voip.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Management' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Management
action: accept
description: Erlaubt Zugriff von LAN auf Management
log: enable
status: disable
position: bottom
src_zones:
- LAN
dst_zones:
- Management
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.management.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Server' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Server
action: accept
description: Erlaubt Zugriff von LAN auf Server
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Server
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.server.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Facility' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Facility
action: accept
description: Erlaubt Zugriff von LAN auf Facility
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Facility
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.facility.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_VOIP' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_VOIP
action: accept
description: Erlaubt Zugriff von LAN auf VOIP
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- VOIP
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.voip.name }}'
service_list:
- Any
state: present
- name: Erstelle 'VPN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: VPN
description: VPN
policy_list:
- INTERNAL_to_bu_RZ
- SSLVPN_to_INTERNAL
policy_type: Any
source_zones:
- VPN
dest_zones:
- Any
state: present
- name: Erstelle 'X to Management' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Management
description: Zugriff auf Management-Netz
policy_list:
- LAN_to_Management
policy_type: Any
source_zones:
- Any
dest_zones:
- Management
state: present
- name: Erstelle 'X to Server' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Server
description: Zugriff auf Server-Netz
policy_list:
- LAN_to_Server
policy_type: Any
source_zones:
- Any
dest_zones:
- Server
state: present
- name: Erstelle 'X to LAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to LAN
description: Zugriff auf LAN-Netz
policy_list:
- LAN_to_LAN_old
policy_type: Any
source_zones:
- Any
dest_zones:
- LAN
state: present
- name: Erstelle 'X to Facility' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Facility
description: Zugriff auf Facility-Netz
policy_list:
- LAN_to_Facility
policy_type: Any
source_zones:
- Any
dest_zones:
- Facility
state: present
- name: Erstelle 'X to VOIP' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to VOIP
description: Zugriff auf VOIP-Netz
policy_list:
- LAN_to_VOIP
policy_type: Any
source_zones:
- Any
dest_zones:
- VOIP
state: present
- name: Erstelle 'X to WAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to WAN
description: X to WAN group
policy_list:
- LAN_to_WAN
- Server_to_WAN
- Management_to_WAN
- LAN_old_to_WAN
- Guest_to_WAN
- Facility_to_WAN
- VOIP_to_WAN
policy_type: Any
source_zones:
- Any
dest_zones:
- WAN
state: present
+3
View File
@@ -0,0 +1,3 @@
# sophos_customer_formicon
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
@@ -0,0 +1,231 @@
---
# Customer-specific firewall policy preserved from the uploaded source.
- name: Update hostname settings
sophos.sophos_firewall.sfos_admin_settings:
hostname_settings:
hostname: '{{ hostname }}'
state: updated
- name: Netzwerke als IP-Hosts in der Firewall anlegen
sophos.sophos_firewall.sfos_ip_host:
name: '{{ item.value.name }}'
network: '{{ item.value.network }}'
mask: '{{ item.value.subnetmask }}'
host_type: network
state: present
loop: '{{ network_objects | dict2items }}'
- name: Zonen erstellen
sophos.sophos_firewall.sfos_zone:
name: '{{ item.value.zone_name }}'
description: '{{ item.value.zone_description }}'
zone_type: '{{ item.value.zone_type }}'
state: present
loop: '{{ vlan_interfaces | dict2items }}'
when: item.value.name != "LAN"
- name: Update Management Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Management
https: Enable
ssh: Enable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Add VLAN Interfaces
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VLAN
data: |
<VLAN>
<Name>{{ item.value.name }}</Name>
<Hardware>Port1</Hardware>
<Interface>Port1</Interface>
<Zone>{{ item.value.zone_name }}</Zone>
<VLANID>{{ item.value.vlan_id }}</VLANID>
<IPv4Configuration>Enable</IPv4Configuration>
<IPv4Assignment>Static</IPv4Assignment>
<IPAddress>{{ item.value.ip_address }}</IPAddress>
<Netmask>{{ item.value.subnetmask }}</Netmask>
</VLAN>
state: present
loop: '{{ vlan_interfaces | dict2items }}'
loop_control:
label: '{{ item.key }} -> VLAN {{ item.value.vlan_id }}'
- name: Erstelle 'LAN_to_LAN_old' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_LAN_old
action: accept
description: Erlaubt Zugriff von LAN auf Bestandsnetz
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- LAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.lan_old.name }}'
service_list:
- Any
state: present
- name: Erstelle 'INTERNAL_to_FHAZUREGWC_LAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: INTERNAL_to_FHAZUREGWC_LAN
action: accept
description: Erlaubt Zugriff von internen Netzen auf Formicon Holding Azure Germany West Central LAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
- Management
dst_zones:
- VPN
src_networks:
- '{{ network_objects.lan_old.name }}'
- '{{ network_objects.management.name }}'
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.azuregwc_lan.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WAN
action: accept
description: Erlaubt Zugriff von LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_old_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_old_to_WAN
action: accept
description: Erlaubt Zugriff von old LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.lan_old.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Management_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Management_to_WAN
action: accept
description: Erlaubt Zugriff von Management auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Management
dst_zones:
- WAN
src_networks:
- '{{ network_objects.management.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Management' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Management
action: accept
description: Erlaubt Zugriff von LAN auf Management
log: enable
status: disable
position: bottom
src_zones:
- LAN
dst_zones:
- Management
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.management.name }}'
service_list:
- Any
state: present
- name: Erstelle 'VPN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: VPN
description: VPN
policy_list:
- INTERNAL_to_FHAZUREGWC_LAN
policy_type: Any
source_zones:
- VPN
dest_zones:
- Any
state: present
- name: Erstelle 'X to Management' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Management
description: Zugriff auf Management-Netz
policy_list:
- LAN_to_Management
policy_type: Any
source_zones:
- Any
dest_zones:
- Management
state: present
- name: Erstelle 'X to LAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to LAN
description: Zugriff auf LAN-Netz
policy_list:
- LAN_to_LAN_old
policy_type: Any
source_zones:
- Any
dest_zones:
- LAN
state: present
- name: Erstelle 'X to WAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to WAN
description: X to WAN group
policy_list:
- LAN_to_WAN
- Management_to_WAN
- LAN_old_to_WAN
policy_type: Any
source_zones:
- Any
dest_zones:
- WAN
state: present
@@ -0,0 +1,3 @@
# sophos_customer_gebhardt_stahl
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
@@ -0,0 +1,195 @@
---
# Customer-specific firewall policy preserved from the uploaded source.
- name: Update hostname settings
sophos.sophos_firewall.sfos_admin_settings:
hostname_settings:
hostname: '{{ hostname }}'
state: updated
- name: Netzwerke als IP-Hosts in der Firewall anlegen
sophos.sophos_firewall.sfos_ip_host:
name: '{{ item.value.name }}'
network: '{{ item.value.network }}'
mask: '{{ item.value.subnetmask }}'
host_type: network
state: present
loop: '{{ network_objects | dict2items }}'
- name: Zonen erstellen
sophos.sophos_firewall.sfos_zone:
name: '{{ item.value.zone_name }}'
description: '{{ item.value.zone_description }}'
zone_type: '{{ item.value.zone_type }}'
state: present
loop: '{{ vlan_interfaces | dict2items }}'
when: item.value.name != "LAN"
- name: Add VLAN Interfaces
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VLAN
data: |
<VLAN>
<Name>{{ item.value.name }}</Name>
<Hardware>Port1</Hardware>
<Interface>Port1</Interface>
<Zone>{{ item.value.zone_name }}</Zone>
<VLANID>{{ item.value.vlan_id }}</VLANID>
<IPv4Configuration>Enable</IPv4Configuration>
<IPv4Assignment>Static</IPv4Assignment>
<IPAddress>{{ item.value.ip_address }}</IPAddress>
<Netmask>{{ item.value.subnetmask }}</Netmask>
</VLAN>
state: present
loop: '{{ vlan_interfaces | dict2items }}'
loop_control:
label: '{{ item.key }} -> VLAN {{ item.value.vlan_id }}'
- name: Erstelle 'LAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WAN
action: accept
description: Erlaubt Zugriff von LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Guest_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Guest_to_WAN
action: accept
description: Erlaubt Zugriff von Guest auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Guest
dst_zones:
- WAN
src_networks:
- '{{ network_objects.guest.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Drucker_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Drucker_to_WAN
action: accept
description: Erlaubt Zugriff von Drucker auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Drucker
dst_zones:
- WAN
src_networks:
- '{{ network_objects.drucker.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'WLAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: WLAN_to_WAN
action: accept
description: Erlaubt Zugriff von WLAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- WLAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.wlan.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Drucker' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Drucker
action: accept
description: Erlaubt Zugriff von LAN auf Drucker
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Drucker
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.drucker.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_WLAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WLAN
action: accept
description: Erlaubt Zugriff von LAN auf WLAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WLAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.wlan.name }}'
service_list:
- Any
state: present
- name: Erstelle 'X to Drucker' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Drucker
description: Zugriff auf Drucker-Netz
policy_list:
- LAN_to_Drucker
policy_type: Any
source_zones:
- Any
dest_zones:
- Drucker
state: present
- name: Erstelle 'X to WLAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to WLAN
description: Zugriff auf WLAN-Netz
policy_list:
- LAN_to_WLAN
policy_type: Any
source_zones:
- Any
dest_zones:
- WLAN
state: present
- name: Erstelle 'X to WAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to WAN
description: X to WAN group
policy_list:
- LAN_to_WAN
- Guest_to_WAN
- Drucker_to_WAN
- WLAN_to_WAN
policy_type: Any
source_zones:
- Any
dest_zones:
- WAN
state: present
@@ -0,0 +1,3 @@
# sophos_customer_hungeling_und_toechter
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
@@ -0,0 +1,268 @@
---
# Customer-specific firewall policy preserved from the uploaded source.
- name: Update hostname settings
sophos.sophos_firewall.sfos_admin_settings:
hostname_settings:
hostname: '{{ hostname }}'
state: updated
- name: Netzwerke als IP-Hosts in der Firewall anlegen
sophos.sophos_firewall.sfos_ip_host:
name: '{{ item.value.name }}'
network: '{{ item.value.network }}'
mask: '{{ item.value.subnetmask }}'
host_type: network
state: present
loop: '{{ network_objects | dict2items }}'
- name: Zonen erstellen
sophos.sophos_firewall.sfos_zone:
name: '{{ item.value.zone_name }}'
description: '{{ item.value.zone_description }}'
zone_type: '{{ item.value.zone_type }}'
state: present
loop: '{{ vlan_interfaces | dict2items }}'
when: item.value.name != "LAN"
- name: Update Management Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Management
https: Enable
ssh: Enable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Add VLAN Interfaces
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VLAN
data: |
<VLAN>
<Name>{{ item.value.name }}</Name>
<Hardware>Port1</Hardware>
<Interface>Port1</Interface>
<Zone>{{ item.value.zone_name }}</Zone>
<VLANID>{{ item.value.vlan_id }}</VLANID>
<IPv4Configuration>Enable</IPv4Configuration>
<IPv4Assignment>Static</IPv4Assignment>
<IPAddress>{{ item.value.ip_address }}</IPAddress>
<Netmask>{{ item.value.subnetmask }}</Netmask>
</VLAN>
state: present
loop: '{{ vlan_interfaces | dict2items }}'
loop_control:
label: '{{ item.key }} -> VLAN {{ item.value.vlan_id }}'
- name: Erstelle 'LAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WAN
action: accept
description: Erlaubt Zugriff von LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Management_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Management_to_WAN
action: accept
description: Erlaubt Zugriff von Management auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Management
dst_zones:
- WAN
src_networks:
- '{{ network_objects.management.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Guest_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Guest_to_WAN
action: accept
description: Erlaubt Zugriff von Guest auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Guest
dst_zones:
- WAN
src_networks:
- '{{ network_objects.guest.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Facility_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Facility_to_WAN
action: accept
description: Erlaubt Zugriff von Facility auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Facility
dst_zones:
- WAN
src_networks:
- '{{ network_objects.facility.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'VOIP_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: VOIP_to_WAN
action: accept
description: Erlaubt Zugriff von VOIP auf WAN
log: enable
status: enable
position: bottom
src_zones:
- VOIP
dst_zones:
- WAN
src_networks:
- '{{ network_objects.voip.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Management' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Management
action: accept
description: Erlaubt Zugriff von LAN auf Management
log: enable
status: disable
position: bottom
src_zones:
- LAN
dst_zones:
- Management
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.management.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Facility' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Facility
action: accept
description: Erlaubt Zugriff von LAN auf Facility
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Facility
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.facility.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_VOIP' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_VOIP
action: accept
description: Erlaubt Zugriff von LAN auf VOIP
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- VOIP
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.voip.name }}'
service_list:
- Any
state: present
- name: Erstelle 'X to Management' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Management
description: Zugriff auf Management-Netz
policy_list:
- LAN_to_Management
policy_type: Any
source_zones:
- Any
dest_zones:
- Management
state: present
- name: Erstelle 'X to Facility' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Facility
description: Zugriff auf Facility-Netz
policy_list:
- LAN_to_Facility
policy_type: Any
source_zones:
- Any
dest_zones:
- Facility
state: present
- name: Erstelle 'X to VOIP' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to VOIP
description: Zugriff auf VOIP-Netz
policy_list:
- LAN_to_VOIP
policy_type: Any
source_zones:
- Any
dest_zones:
- VOIP
state: present
- name: Erstelle 'X to WAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to WAN
description: X to WAN group
policy_list:
- LAN_to_WAN
- Management_to_WAN
- Guest_to_WAN
- Facility_to_WAN
- VOIP_to_WAN
policy_type: Any
source_zones:
- Any
dest_zones:
- WAN
state: present
@@ -0,0 +1,3 @@
# sophos_customer_koenig_holding_gmbh
Policy-preserving extraction from the uploaded production playbooks. Arguments, conditions, operation order, rule names and values were not changed. Invoke through the matching playbook.
@@ -0,0 +1,407 @@
---
# Customer-specific firewall policy preserved from the uploaded source.
- name: Update hostname settings
sophos.sophos_firewall.sfos_admin_settings:
hostname_settings:
hostname: '{{ hostname }}'
state: updated
- name: Netzwerke als IP-Hosts in der Firewall anlegen
sophos.sophos_firewall.sfos_ip_host:
name: '{{ item.value.name }}'
network: '{{ item.value.network }}'
mask: '{{ item.value.subnetmask }}'
host_type: network
state: present
loop: '{{ network_objects | dict2items }}'
- name: Zonen erstellen
sophos.sophos_firewall.sfos_zone:
name: '{{ item.value.zone_name }}'
description: '{{ item.value.zone_description }}'
zone_type: '{{ item.value.zone_type }}'
state: present
loop: '{{ vlan_interfaces | dict2items }}'
when: item.value.name != "LAN"
- name: Update Management Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Management
https: Enable
ssh: Enable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update Server Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Server
https: Enable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update Guest Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Guest
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update Facility Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: Facility
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Update VOIP Zone Admin Services
sophos.sophos_firewall.sfos_zone:
name: VOIP
https: Disable
ssh: Disable
ad_sso: Disable
captive_portal: Disable
radius_sso: Disable
client_authen: Disable
chromebook_sso: Disable
ping: Enable
dns: Enable
ipsec: Disable
sslvpn: Disable
vpn_portal: Disable
red: Disable
wireless_protection: Disable
web_proxy: Disable
user_portal: Disable
smtp_relay: Disable
snmp: Disable
state: updated
- name: Add VLAN Interfaces
sophos.sophos_firewall.sfos_xmlapi:
xml_tag: VLAN
data: |
<VLAN>
<Name>{{ item.value.name }}</Name>
<Hardware>Port1</Hardware>
<Interface>Port1</Interface>
<Zone>{{ item.value.zone_name }}</Zone>
<VLANID>{{ item.value.vlan_id }}</VLANID>
<IPv4Configuration>Enable</IPv4Configuration>
<IPv4Assignment>Static</IPv4Assignment>
<IPAddress>{{ item.value.ip_address }}</IPAddress>
<Netmask>{{ item.value.subnetmask }}</Netmask>
</VLAN>
state: present
loop: '{{ vlan_interfaces | dict2items }}'
loop_control:
label: '{{ item.key }} -> VLAN {{ item.value.vlan_id }}'
- name: Erstelle 'LAN_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_WAN
action: accept
description: Erlaubt Zugriff von LAN auf WAN
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- WAN
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Server_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Server_to_WAN
action: accept
description: Erlaubt Zugriff von Server auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Server
dst_zones:
- WAN
src_networks:
- '{{ network_objects.server.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Management_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Management_to_WAN
action: accept
description: Erlaubt Zugriff von Management auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Management
dst_zones:
- WAN
src_networks:
- '{{ network_objects.management.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Guest_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Guest_to_WAN
action: accept
description: Erlaubt Zugriff von Guest auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Guest
dst_zones:
- WAN
src_networks:
- '{{ network_objects.guest.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'Facility_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: Facility_to_WAN
action: accept
description: Erlaubt Zugriff von Facility auf WAN
log: enable
status: enable
position: bottom
src_zones:
- Facility
dst_zones:
- WAN
src_networks:
- '{{ network_objects.facility.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'VOIP_to_WAN' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: VOIP_to_WAN
action: accept
description: Erlaubt Zugriff von VOIP auf WAN
log: enable
status: enable
position: bottom
src_zones:
- VOIP
dst_zones:
- WAN
src_networks:
- '{{ network_objects.voip.name }}'
dst_networks:
- Any
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Management' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Management
action: accept
description: Erlaubt Zugriff von LAN auf Management
log: enable
status: disable
position: bottom
src_zones:
- LAN
dst_zones:
- Management
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.management.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Server' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Server
action: accept
description: Erlaubt Zugriff von LAN auf Server
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Server
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.server.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_Facility' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_Facility
action: accept
description: Erlaubt Zugriff von LAN auf Facility
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- Facility
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.facility.name }}'
service_list:
- Any
state: present
- name: Erstelle 'LAN_to_VOIP' Firewall-Regel
sophos.sophos_firewall.sfos_firewall_rule:
name: LAN_to_VOIP
action: accept
description: Erlaubt Zugriff von LAN auf VOIP
log: enable
status: enable
position: bottom
src_zones:
- LAN
dst_zones:
- VOIP
src_networks:
- '{{ network_objects.office.name }}'
dst_networks:
- '{{ network_objects.voip.name }}'
service_list:
- Any
state: present
- name: Erstelle 'X to Management' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Management
description: Zugriff auf Management-Netz
policy_list:
- LAN_to_Management
policy_type: Any
source_zones:
- Any
dest_zones:
- Management
state: present
- name: Erstelle 'X to Server' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Server
description: Zugriff auf Server-Netz
policy_list:
- LAN_to_Server
policy_type: Any
source_zones:
- Any
dest_zones:
- Server
state: present
- name: Erstelle 'X to Facility' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to Facility
description: Zugriff auf Facility-Netz
policy_list:
- LAN_to_Facility
policy_type: Any
source_zones:
- Any
dest_zones:
- Facility
state: present
- name: Erstelle 'X to VOIP' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to VOIP
description: Zugriff auf VOIP-Netz
policy_list:
- LAN_to_VOIP
policy_type: Any
source_zones:
- Any
dest_zones:
- VOIP
state: present
- name: Erstelle 'X to WAN' Firewall-Regel Gruppe
sophos.sophos_firewall.sfos_firewall_rulegroup:
name: X to WAN
description: X to WAN group
policy_list:
- LAN_to_WAN
- Server_to_WAN
- Management_to_WAN
- Guest_to_WAN
- Facility_to_WAN
- VOIP_to_WAN
policy_type: Any
source_zones:
- Any
dest_zones:
- WAN
state: present
+31
View File
@@ -0,0 +1,31 @@
# system_detect_roles
Operator defaults are intentionally low-precedence; inventory and explicit run options may override them.
```yaml
---
# Windows feature & service identifiers
ad_ds_feature_name: AD-Domain-Services
dhcp_windows_service_name: DHCPServer
veeam_services:
vbr: VeeamBackupSvc
vbo: Veeam.Archiver.Service
em: VeeamEnterpriseManagerSvc
unifi_linux_services:
- unifi
- unifi.service
unifi_linux_packages:
- unifi
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
```
## Structured result integration
Current reporting behavior and field semantics are specified in
[scripts/docs/OPERATION_RESULTS.md](../../scripts/docs/OPERATION_RESULTS.md).
The calling catalog playbook owns publication; helper roles do not implicitly export
arbitrary facts, module results or debug data. Existing defaults above retain their
precedence. See the current validation/sanity documents before using the new candidate.
@@ -0,0 +1,17 @@
---
# Windows feature & service identifiers
ad_ds_feature_name: AD-Domain-Services
dhcp_windows_service_name: DHCPServer
veeam_services:
vbr: VeeamBackupSvc
vbo: Veeam.Archiver.Service
em: VeeamEnterpriseManagerSvc
unifi_linux_services:
- unifi
- unifi.service
unifi_linux_packages:
- unifi
want_linux_check_certificate: false
want_windows_citrix: false
want_windows_surebackup: false
want_windows_backup: false
+132
View File
@@ -0,0 +1,132 @@
---
# Read-only capability discovery. This does not assign inventory groups.
- name: Windows | Detect AD DS feature (DC)
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_feature_info:
name: '{{ ad_ds_feature_name | default(''AD-Domain-Services'') }}'
register: _win_dc_feature
failed_when: false
- name: 'Windows | Fallback: check NTDS service (DC)'
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: NTDS
register: _win_ntds_svc
failed_when: false
- name: Windows | Check DHCP service
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: '{{ dhcp_windows_service_name | default(''DHCPServer'') }}'
register: _win_dhcp_svc
failed_when: false
- name: Windows | Check Veeam VBR service
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: '{{ veeam_services.vbr | default(''VeeamBackupSvc'') }}'
register: _veeam_vbr
failed_when: false
- name: Windows | Check Veeam VBO service
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: '{{ veeam_services.vbo | default(''Veeam.Archiver.Service'') }}'
register: _veeam_vbo
failed_when: false
- name: Windows | Check Veeam Enterprise Manager service
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: '{{ veeam_services.em | default(''VeeamEnterpriseManagerSvc'') }}'
register: _veeam_em
failed_when: false
- name: Windows | Detect Hyper-V feature
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_feature_info:
name: '{{ hyperv_feature_name | default(''Hyper-V'') }}'
register: _win_hyperv_feature
failed_when: false
- name: 'Windows | Fallback: check Hyper-V VMMS service'
when: ansible_facts['os_family'] == "Windows"
ansible.windows.win_service_info:
name: '{{ hyperv_vmms_service_name | default(''vmms'') }}'
register: _win_hyperv_vmms_svc
failed_when: false
- name: Windows | Set Veeam/DC/DHCP booleans (base)
when: ansible_facts['os_family'] == "Windows"
ansible.builtin.set_fact:
is_dc: |-
{{
(
(_win_dc_feature.features | default([]))
| selectattr('installed')
| list
| length > 0
)
or
(_win_ntds_svc.exists | default(false))
}}
is_dhcp_server: '{{ _win_dhcp_svc.exists | default(false) }}'
has_veeam_vbr: '{{ _veeam_vbr.exists | default(false) }}'
has_veeam_vbo: '{{ _veeam_vbo.exists | default(false) }}'
has_veeam_em: '{{ _veeam_em.exists | default(false) }}'
is_hyperv_host: |-
{{
(
(_win_hyperv_feature.features | default([]))
| selectattr('installed')
| list
| length > 0
)
or
(_win_hyperv_vmms_svc.exists | default(false))
}}
- name: Windows | Debug summary
when:
- ansible_facts['os_family'] == "Windows"
- aim_debug | default(false) | bool
ansible.builtin.debug:
msg:
is_dc: '{{ is_dc }}'
is_dhcp_server: '{{ is_dhcp_server }}'
has_veeam_vbr: '{{ has_veeam_vbr }}'
has_veeam_vbo: '{{ has_veeam_vbo }}'
has_veeam_em: '{{ has_veeam_em }}'
is_hyperv_host: '{{ is_hyperv_host }}'
- name: Linux | Collect service facts
when: ansible_facts['os_family'] != "Windows"
ansible.builtin.service_facts: null
- name: Linux | Collect package facts
when: ansible_facts['os_family'] != "Windows"
ansible.builtin.package_facts:
manager: auto
- name: Linux | Set UniFi flags
when: ansible_facts['os_family'] != "Windows"
vars:
svcs: '{{ ansible_facts.services | default({}) }}'
pkgs: '{{ ansible_facts.packages | default({}) | list }}'
ansible.builtin.set_fact:
is_unifi_controller: |-
{{
(unifi_linux_services | select('in', svcs.keys()) | list | length > 0)
or
(pkgs | intersect(unifi_linux_packages) | length > 0)
}}
is_unifi_os_server: |-
{{
'uosserver.service' in svcs
}}
- name: Linux | Debug summary
when:
- ansible_facts['os_family'] != "Windows"
- aim_debug | default(false) | bool
ansible.builtin.debug:
msg:
is_unifi_controller: '{{ is_unifi_controller }}'
is_unifi_os_server: '{{ is_unifi_os_server }}'
- name: Normalize detection booleans
ansible.builtin.set_fact:
is_dc: '{{ is_dc | default(false) }}'
is_dhcp_server: '{{ is_dhcp_server | default(false) }}'
has_veeam_vbr: '{{ has_veeam_vbr | default(false) }}'
has_veeam_vbo: '{{ has_veeam_vbo | default(false) }}'
has_veeam_em: '{{ has_veeam_em | default(false) }}'
is_unifi_controller: '{{ is_unifi_controller | default(false) }}'
is_unifi_os_server: '{{ is_unifi_os_server | default(false) }}'
is_hyperv_host: '{{ is_hyperv_host | default(false) }}'