108 lines
5.0 KiB
YAML
108 lines
5.0 KiB
YAML
---
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# TEMPLATE: Service State Check
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
#
|
|
# Uses ansible.builtin.service_facts — no shell command needed.
|
|
# service_facts gathers all service states into ansible_facts.services
|
|
# as a dict keyed by service name. Prefer this over shelling out to
|
|
# systemctl for any service-related check.
|
|
#
|
|
# IMPORTANT — run service_facts ONCE per suite, not once per test.
|
|
# Put this gather task at the TOP of your suite file:
|
|
#
|
|
# - name: "Gather: Load all service states"
|
|
# ansible.builtin.service_facts:
|
|
#
|
|
# Then each test block below can query ansible_facts.services without
|
|
# running additional commands.
|
|
#
|
|
# Service dict structure (ansible_facts.services['sshd.service']):
|
|
# name: 'sshd.service'
|
|
# state: 'running' | 'stopped' | 'failed' | 'inactive'
|
|
# status: 'enabled' | 'disabled' | 'masked' | 'static' | 'unknown'
|
|
#
|
|
# Common 'passed' expression patterns:
|
|
#
|
|
# # Service must be running and enabled:
|
|
# 'passed': (
|
|
# ansible_facts.services['sshd.service'] is defined and
|
|
# ansible_facts.services['sshd.service'].state == 'running' and
|
|
# ansible_facts.services['sshd.service'].status == 'enabled'
|
|
# ),
|
|
#
|
|
# # Service must NOT be running (insecure service check):
|
|
# 'passed': (
|
|
# ansible_facts.services['telnet.socket'] is not defined or
|
|
# ansible_facts.services['telnet.socket'].state != 'running'
|
|
# ),
|
|
#
|
|
# # Any of several insecure services must all be absent/inactive:
|
|
# 'passed': (
|
|
# ['telnet.socket', 'rsh.socket', 'ftp.service']
|
|
# | map('extract', ansible_facts.services)
|
|
# | select('defined')
|
|
# | selectattr('state', 'equalto', 'running')
|
|
# | list | length == 0
|
|
# ),
|
|
#
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
|
|
# ── Put this ONCE at the top of the suite file ───────────────────────
|
|
#
|
|
# - name: "Gather: Load all service states (suite-wide)"
|
|
# ansible.builtin.service_facts:
|
|
#
|
|
# ── Per-test blocks below ────────────────────────────────────────────
|
|
|
|
# ── SUITE_ID: Service must be running ───────────────────────────────
|
|
|
|
- block:
|
|
- name: "Evaluate: TEST_ID — SERVICE_NAME is running and enabled"
|
|
ansible.builtin.set_fact:
|
|
test_results: "{{ test_results + [{
|
|
'test_id': 'TEST_ID',
|
|
'category': 'FR_NUMBER — CATEGORY_NAME',
|
|
'requirement': 'SR X.Y — REQUIREMENT_NAME',
|
|
'description': 'SERVICE_NAME shall be running and enabled at boot',
|
|
'passed': (
|
|
ansible_facts.services['SERVICE_NAME.service'] is defined and
|
|
ansible_facts.services['SERVICE_NAME.service'].state == 'running' and
|
|
ansible_facts.services['SERVICE_NAME.service'].status == 'enabled'
|
|
),
|
|
'expected': 'SERVICE_NAME: state=running, status=enabled',
|
|
'actual': (
|
|
'state=' + ansible_facts.services['SERVICE_NAME.service'].state
|
|
+ ', status=' + ansible_facts.services['SERVICE_NAME.service'].status
|
|
) if ansible_facts.services['SERVICE_NAME.service'] is defined
|
|
else 'SERVICE_NAME.service: not found in service facts',
|
|
'severity': 'high',
|
|
'remediation': 'systemctl enable --now SERVICE_NAME'
|
|
}] }}"
|
|
ignore_errors: yes
|
|
|
|
|
|
# ── SUITE_ID: Insecure service must NOT be running ──────────────────
|
|
|
|
- block:
|
|
- name: "Evaluate: TEST_ID — INSECURE_SERVICE_NAME is not running"
|
|
ansible.builtin.set_fact:
|
|
test_results: "{{ test_results + [{
|
|
'test_id': 'TEST_ID',
|
|
'category': 'FR_NUMBER — CATEGORY_NAME',
|
|
'requirement': 'SR X.Y — REQUIREMENT_NAME',
|
|
'description': 'INSECURE_SERVICE_NAME shall be disabled and not running',
|
|
'passed': (
|
|
ansible_facts.services['INSECURE_SERVICE_NAME.service'] is not defined or
|
|
ansible_facts.services['INSECURE_SERVICE_NAME.service'].state != 'running'
|
|
),
|
|
'expected': 'INSECURE_SERVICE_NAME: absent or not running',
|
|
'actual': (
|
|
'state=' + ansible_facts.services['INSECURE_SERVICE_NAME.service'].state
|
|
) if ansible_facts.services['INSECURE_SERVICE_NAME.service'] is defined
|
|
else 'not installed',
|
|
'severity': 'critical',
|
|
'remediation': 'systemctl disable --now INSECURE_SERVICE_NAME'
|
|
}] }}"
|
|
ignore_errors: yes
|