mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
roles/sys-svc-mail-msmtp/tasks/ca_bundle.yml stat'ed candidate bundle paths on
the Ansible target and wrote the winner into msmtprc. Moodle and WordSpress then
copied that file into a container, where the named path is a different file - or
none. Only update-ca-certificates populates a container's system bundle, and
that runs solely from the with-ca-trust.sh entrypoint, which compose_ca.py sets
only when 'docker image inspect' succeeded. On a fresh host the image is built
minutes later, so it never ran: job 94965457602 of run 31864448027 shows
Config.Entrypoint still moodle-entrypoint.sh while the CA sits mounted beside it,
and msmtp reporting 'The certificate issuer is unknown'.
An explicit tls_trust_file also outranks SSL_CERT_FILE, so the env injection the
override always performs could not compensate.
Name CA_TRUST.inject_cert_container when the CA is actually injected, and emit
no line at all otherwise - msmtp's own 'system' default is the right answer for
a letsencrypt relay, and it is what the container's stock bundle verifies. This
also removes a latent defect on letsencrypt: a RedHat host would have written
/etc/pki/... into a Debian container.
The removal of the probing apparatus is taken from 9a72d01eb on
fork/feature/ai-agent-employees, which diagnosed the wrong-machine measurement
correctly. Its own conclusion - drop the line entirely and rely on the trust
store - does not hold where the wrapper never runs, and in swarm it never does:
handlers/swarm.yml passes wrapper=False by design.
The three-term predicate behind all of this was hand-copied into four places.
lookup('ca_injected', application_id) is now its single source; the swarm and
compose gates and sys-svc-compose-ca's own var read it too.
compose_ca.py finally says when it degrades to mount-plus-env, naming the service
and the image it could not inspect.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
60 lines
2.2 KiB
Python
60 lines
2.2 KiB
Python
"""Lookup `ca_injected`: whether the self-signed root CA is mounted into an
|
|
application's containers.
|
|
|
|
{{ lookup('ca_injected', application_id) }}
|
|
|
|
The CA override that bind-mounts ``CA_TRUST.inject_cert_container`` is emitted
|
|
under three conditions, and anything that reads the mounted file must ask the
|
|
same three or it will point at a path that was never mounted. The conditions
|
|
lived as four hand-copied expressions - both `sys-svc-compose` handlers,
|
|
`sys-svc-compose-ca/vars/main.yml` and the msmtp template - which is one copy
|
|
per place that can drift.
|
|
|
|
Returns a plain bool, so callers read as a predicate:
|
|
|
|
when: lookup('ca_injected', application_id)
|
|
{{ CA_TRUST.inject_cert_container if lookup('ca_injected', application_id) else ... }}
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from ansible.errors import AnsibleError
|
|
from ansible.module_utils.parsing.convert_bool import boolean as _to_bool
|
|
from ansible.plugins.loader import lookup_loader
|
|
from ansible.plugins.lookup import LookupBase
|
|
|
|
from plugins.filter.has.domain import has_domain
|
|
|
|
SELF_SIGNED_MODE = "self_signed"
|
|
|
|
|
|
class LookupModule(LookupBase):
|
|
def run(
|
|
self,
|
|
terms: list[Any] | None,
|
|
variables: dict[str, Any] | None = None,
|
|
**kwargs: Any,
|
|
) -> list[bool]:
|
|
if not terms or len(terms) != 1:
|
|
raise AnsibleError(
|
|
"ca_injected lookup requires exactly one term: the application id"
|
|
)
|
|
templar = getattr(self, "_templar", None)
|
|
raw = templar.template(terms[0]) if templar is not None else terms[0]
|
|
application_id = str(raw).strip()
|
|
if not application_id:
|
|
raise AnsibleError("ca_injected lookup: application id must be non-empty")
|
|
|
|
def _run(name: str, args: list[Any]) -> Any:
|
|
return lookup_loader.get(name, loader=self._loader, templar=templar).run(
|
|
args, variables=variables or {}
|
|
)[0]
|
|
|
|
if not has_domain(_run("domains", []), application_id):
|
|
return [False]
|
|
if not _to_bool(_run("tls", [application_id, "enabled"])):
|
|
return [False]
|
|
return [_run("tls", [application_id, "mode"]) == SELF_SIGNED_MODE]
|