- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Managed Azure must-gathers use a flat pod structure where all container
logs are combined into a single file (pods/<pod>/logs/logs.txt) with
delimiter headers separating each container's output:
==== START logs for container <name> of pod <pod> ====
Previously, only hub logs were discovered because hub-web pods retain the
standard OCP container directory structure (web/web/logs/). Controller
pods use the flat structure, causing their logs to be completely missed
— no ComponentReport was created and direct-access hits were not reported.
This occurred due to three compounding defects:
1. The _is_web_container() gate rejected the "logs/" directory name,
causing the entire pod to be skipped via continue
2. The file extension filter only accepted .log and .log.gz, which would
have rejected logs.txt even if discovered
3. No logic existed to parse container delimiter headers and filter out
non-web container sections (redis, rsyslog, etc.)
This fix adds:
- A _filter_by_container_delimiter() helper that recognizes delimiter
headers and filters to only web container sections
- Auto-detection in _open_log_file() that transparently applies delimiter
filtering when the pattern is detected
- A flat-structure fallback in _find_must_gather_logs() that activates
only when no standard container directories are found, accepting .txt
files and using _component_from_pod_name() for classification
- Five comprehensive test cases covering flat structure scenarios,
backward compatibility, and edge cases
The changes maintain full backward compatibility — standard OCP
must-gathers continue to work unchanged, and all 64 existing tests pass
along with the 5 new tests (69 total).
Signed-off-by: Max Mitschke <mmitschk@redhat.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
|
||
| src/aap_detect_direct_component_access | ||
| tests | ||
| .gitignore | ||
| pyproject.toml | ||
| README.md | ||
aap-detect-direct-component-access
Detect direct API access to Ansible Automation Platform (AAP) components by analyzing nginx access logs.
AAP 2.7 requires all API traffic to flow through the AAP Gateway. This
tool scans nginx access logs from Controller, Hub, and EDA components to
identify requests that bypass the gateway — i.e. requests that arrive
without the X-Trusted-Proxy header and without a DAB JWT token.
Requirements
- Python 3.6+ (no third-party dependencies)
Installation
With uvx (recommended, no install needed)
uvx --from "git+https://github.com/ansible/aap-detect-direct-component-access" aap-detect-direct-component-access /path/to/sosreport
With pip
pip install "git+https://github.com/ansible/aap-detect-direct-component-access"
aap-detect-direct-component-access /path/to/sosreport
Without installing
python -m aap_detect_direct_component_access /path/to/sosreport
Or run the script directly:
python src/aap_detect_direct_component_access/detect.py /path/to/sosreport
Usage
aap-detect-direct-component-access [-h] [-o OUTPUT_DIR] [--include-filtered] [-V] input
Arguments
| Argument | Description |
|---|---|
input |
Path to a SOSReport directory, must-gather directory, or individual nginx access log file |
-o, --output-dir |
Directory to write report files (default: .) |
--include-filtered |
Include health checks and probe requests in the report |
-V, --version |
Show version and exit |
Input formats
The tool auto-detects the input format:
- SOSReport — detected by
var/log/containers/orvar/log/pods/directory structure - must-gather — detected by
namespaces/directory structure (OpenShift) - Log file — any individual nginx access log file (plain text or gzipped)
Expected nginx log format
The tool requires nginx logs with the ANSTRAT-1840 marker fields appended:
$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent
"$http_referer" "$http_user_agent" "$http_x_forwarded_for"
$trusted_proxy_present $dab_jwt_present
If logs use the legacy format (without the trailing marker fields), the tool will report them as "legacy format" and exit with code 3.
Output
- stdout — summary with total requests, direct access count per component
<input-name>.report.txt— detailed breakdown by path and source IP<input-name>.raw.log— raw nginx log lines flagged as direct access
Exit codes
| Code | Meaning |
|---|---|
| 0 | No direct access detected |
| 1 | Error (bad input path, no logs found) |
| 2 | Direct access detected |
| 3 | Legacy log format (cannot determine) |
Filtered requests
By default, the following are excluded from the direct-access report since they represent expected internal traffic:
- Health check endpoints (
/api/v2/ping,/healthz,/readyz, etc.) - Static assets (
/static/,/favicon.ico) - Kubernetes probes (identified by
kube-probeuser-agent) - Internal monitoring (
/nginx_status,/_debug/)
Use --include-filtered to include these in the report.
Running tests
python -m pytest tests/
Or without pytest:
python -m unittest discover -s tests
License
Apache-2.0