--- # ══════════════════════════════════════════════════════════════════════ # TEMPLATE: Automated Shell-Based Test # ══════════════════════════════════════════════════════════════════════ # # The standard gather → evaluate pattern used throughout this framework. # Copy this block into the appropriate FR suite file (suites/frN_*.yml) # and fill in all UPPERCASE placeholders. # # How to use: # 1. Copy the block below into suites/frN_category.yml # 2. Replace every UPPERCASE placeholder # 3. Write your gather shell command to produce meaningful stdout # 4. Write the 'passed' Jinja2 expression that evaluates the result # 5. Set severity: critical | high | medium | low # # Pass/fail expression patterns: # # # Empty output means no findings (good): # 'passed': (_result.stdout | trim | length == 0), # # # Numeric threshold (value must exist and be within range): # 'passed': ( # _result.stdout | trim | regex_search('^[0-9]+$') and # (_result.stdout | trim | int > 0) and # (_result.stdout | trim | int <= 90) # ), # # # Extract a number from labelled output (e.g. "minlen = 14"): # 'passed': ( # (_result.stdout | regex_search('label\s*=\s*(\d+)', '\1') # | default(['0'], true) | first | int) >= 14 # ), # # # String match: # 'passed': (_result.stdout | trim == 'expected_value'), # # # Specific value is absent: # 'passed': ('dangerous_string' not in _result.stdout), # # ══════════════════════════════════════════════════════════════════════ # ── SUITE_ID: SHORT_DESCRIPTION ───────────────────────────────────── - block: - name: "Gather: DESCRIBE_WHAT_IS_COLLECTED" ansible.builtin.shell: | # Replace with your data collection command. # Guidelines: # - Use grep/awk/cut to narrow output to only the relevant data. # - Produce empty stdout when no finding exists (makes 'passed' easy). # - Exit 0 always; let Ansible evaluate the output, not the exit code. echo "replace_me" register: _result changed_when: false - name: "Evaluate: TEST_ID" ansible.builtin.set_fact: test_results: "{{ test_results + [{ 'test_id': 'TEST_ID', 'category': 'FR_NUMBER — CATEGORY_NAME', 'requirement': 'SR X.Y — REQUIREMENT_NAME', 'description': 'One-line description of what is being checked', 'passed': (_result.stdout | trim | length == 0), 'expected': 'What a passing system looks like', 'actual': (_result.stdout | trim | default('OK', true)), 'severity': 'high', 'remediation': 'Exact command or configuration change to fix this finding' }] }}" ignore_errors: yes