fix(agent): add unprivileged nginx preflight
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m31s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 1m7s

This commit is contained in:
ogt
2026-07-10 22:15:26 +08:00
parent e9d2579471
commit aceef51c87
3 changed files with 98 additions and 0 deletions

View File

@@ -116,6 +116,7 @@ _CATALOG: tuple[dict[str, Any], ...] = (
{
"catalog_id": "ansible:nginx-sync",
"playbook_path": "infra/ansible/playbooks/nginx-sync.yml",
"check_mode_playbook_path": "infra/ansible/playbooks/nginx-sync-readonly.yml",
"inventory_hosts": ["host_110", "host_188"],
"domains": ["nginx", "proxy", "ollama_proxy", "tls"],
"keywords": ["nginx", "proxy", "ollama", "gcp", "tls", "cert", "502", "upstream"],

View File

@@ -1294,6 +1294,9 @@ def test_ansible_truth_keeps_catalog_hint_separate_from_runtime_use() -> None:
assert truth["records"] == []
assert truth["not_used_reason"].startswith("no automation_operation_log row")
assert truth["candidate_catalog"]["candidates"][0]["catalog_id"] == "ansible:nginx-sync"
assert truth["candidate_catalog"]["candidates"][0]["check_mode_playbook_path"] == (
"infra/ansible/playbooks/nginx-sync-readonly.yml"
)
assert truth["candidate_catalog"]["candidates"][0]["approval_required"] is False
assert truth["candidate_catalog"]["decision_effect"] == "none"

View File

@@ -0,0 +1,94 @@
---
# Read-only preflight for the nginx-sync catalog entry.
# This path never uses sudo and remains safe when the privileged apply executor
# is unavailable. The mutating nginx-sync.yml remains the controlled apply path.
- name: "188 Nginx read-only evidence"
hosts: host_188
gather_facts: false
become: false
tasks:
- name: "Preflight | collect remote user"
ansible.builtin.command:
cmd: "id -un"
register: remote_identity
changed_when: false
check_mode: false
- name: "Nginx | inspect public gateway configuration"
ansible.builtin.stat:
path: /etc/nginx/sites-enabled/all-sites.conf
register: public_gateway_config
failed_when: false
- name: "Nginx | inspect internal tools HTTPS configuration"
ansible.builtin.stat:
path: /etc/nginx/sites-enabled/188-internal-tools-https.conf
register: internal_tools_config
failed_when: false
- name: "Nginx | collect listening sockets"
ansible.builtin.command:
cmd: "ss -ltn"
register: listening_sockets
changed_when: false
failed_when: false
check_mode: false
- name: "Evidence | emit 188 read-only summary"
ansible.builtin.debug:
msg:
remote_user: "{{ remote_identity.stdout | default('unknown') }}"
public_gateway_config_present: "{{ public_gateway_config.stat.exists | default(false) }}"
internal_tools_config_present: "{{ internal_tools_config.stat.exists | default(false) }}"
https_listener_present: "{{ ':443 ' in (listening_sockets.stdout | default('')) }}"
- name: "110 Ollama proxy read-only evidence"
hosts: host_110
gather_facts: false
become: false
tasks:
- name: "Preflight | collect remote user"
ansible.builtin.command:
cmd: "id -un"
register: remote_identity
changed_when: false
check_mode: false
- name: "Nginx | inspect managed Ollama proxy configuration"
ansible.builtin.stat:
path: /etc/nginx/sites-enabled/110-ollama-proxy.conf
register: managed_proxy_config
failed_when: false
- name: "Nginx | inspect stale Ollama proxy configuration"
ansible.builtin.stat:
path: /etc/nginx/conf.d/ollama-gcp-proxy.conf
register: stale_proxy_config
failed_when: false
- name: "Ollama | probe configured proxy listeners"
ansible.builtin.uri:
url: "http://127.0.0.1:{{ item }}/api/tags"
method: GET
return_content: false
status_code: [200, 502, 503, 504]
timeout: 6
loop:
- 11435
- 11436
- 11437
register: proxy_health
failed_when: false
changed_when: false
check_mode: false
- name: "Evidence | emit 110 read-only summary"
ansible.builtin.debug:
msg:
remote_user: "{{ remote_identity.stdout | default('unknown') }}"
managed_proxy_config_present: "{{ managed_proxy_config.stat.exists | default(false) }}"
stale_proxy_config_present: "{{ stale_proxy_config.stat.exists | default(false) }}"
proxy_http_statuses: "{{ proxy_health.results | default([]) | map(attribute='status', default=-1) | list }}"